Contract 0x95dCaDDaa40aC726BF4734754e6B75eAe6F5eb9F

Contract Overview

Balance:
0 Ether
Txn Hash Method
Block
From
To
Value
0x98d0ed29e5481f22a75ae1131d4deefaab3c452b62832bfe2b4e219c3081e2f5Rebuild Market C...248081662021-05-13 4:55:205 days 16 hrs ago0x73570075092502472e4b61a7058df1a4a1db12f2 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.042631200
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916Rebuild Market C...248081642021-05-13 4:55:085 days 16 hrs ago0x73570075092502472e4b61a7058df1a4a1db12f2 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.1748596200
0xa70fb8253ae5471d20369e7c80fa9b0e66a513f0fadb1c3ecd50fcc684dfe7ffRebuild Market C...248081632021-05-13 4:55:005 days 16 hrs ago0x73570075092502472e4b61a7058df1a4a1db12f2 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.182064200
0xc1194fa03439d6a32b8a953592ea4294003c77b041561f940328a4038b934ff6Rebuild Market C...248080382021-05-13 4:42:445 days 16 hrs ago0x73570075092502472e4b61a7058df1a4a1db12f2 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.042631200
0xa8b57f11b8c3244ff04de20b12b6b675625ab14026004efeb50cc73ca140f47eRebuild Market C...248080372021-05-13 4:42:365 days 16 hrs ago0x73570075092502472e4b61a7058df1a4a1db12f2 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.1748596200
0x6e0874d1a71748986bfe2349bf0495c17903691a596b085eb1f788f9d0b3b3ccRebuild Market C...248080362021-05-13 4:42:325 days 16 hrs ago0x73570075092502472e4b61a7058df1a4a1db12f2 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.182064200
0x1c22cf3abc7fffe33d3b780dc4f8f36051e806e5a0a84d4bf33206601407b43fAccept Ownership243386112021-04-19 21:36:2828 days 23 hrs ago0x73570075092502472e4b61a7058df1a4a1db12f2 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.0000217641
0xa25f57e0abf55f642a09ebf0ae8539e1d243a61441145269b0a8ffc8901cbeb4Nominate New Own...243376782021-04-19 20:33:2029 days 23 mins ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.0000444811
0xa14b463dbc4489adc11f0241d0ac84525fdc17df5ed0aec1fcc3a3a61b1e933fCreate Market241032772021-03-30 13:35:5649 days 7 hrs ago0xb8d08d9537fc8e5624c298302137c5b5ce2f301d IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.68119844130
0x36266102de5a54336ae77bcd00daa1e0b265203c32c3164da0949a10b7e794ceRebuild Market C...240317732021-03-23 19:50:2056 days 1 hr ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.0011688541
0x485ad636dace107f8174eebb993c6996ad50fa6bb132a4bab39e1dbcc2fc7d58Rebuild Market C...240317712021-03-23 19:50:0456 days 1 hr ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.001229321
0x7294b48945547d82e01578ca03eb385940b06b77eb2e5682f79c516f4bef6f2aCreate Market240107092021-03-21 20:36:2858 days 20 mins ago0x9f8e4ee788d9b00a3409584e18034aa7b736c396 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.940096723179
0x3e607ea63e8ea52841b56bb45f99f84096b0c7ea6a3f636ab8822f3f38c3db95Create Market239768212021-03-18 17:00:2861 days 3 hrs ago0x461783a831e6db52d68ba2f3194f6fd1e0087e04 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether1.024123035195
0xd5475c682ba2b41b86402a166c343daf6a94c63d1af99335174270e0ec3c9bf5Create Market239743932021-03-18 11:36:0461 days 9 hrs ago0x461783a831e6db52d68ba2f3194f6fd1e0087e04 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.724767306138
0x4a161e59fd7ca8df080d9c701105547402b80c7a29bb2b041a017aa54fa1e000Create Market239673432021-03-17 21:07:0861 days 23 hrs ago0x9f8e4ee788d9b00a3409584e18034aa7b736c396 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.80879645154
0x9dc7cff328b4d9847c476180913d387369f4ba17a2d6de96611bfb6a4df68b29Expire Markets228656492021-01-03 9:12:52135 days 11 hrs ago0xe51a50e95c5a92cb4650eacf6ffcb3eb25c7a012 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.0002718210
0x5697e6255fda014afa434745064f8509efcb998adc01f0a4114a1b701bbbcb55Expire Markets228585282021-01-02 19:45:12136 days 1 hr ago0xe51a50e95c5a92cb4650eacf6ffcb3eb25c7a012 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.0000268141
0x38c3de2d53b57e47802ee747407ee755fbb40ec9ebe85fcea51483d7c0625b75Expire Markets228418502021-01-01 12:08:20137 days 8 hrs ago0x57170b6ae91d06102ec7d984d551d590ce1504e5 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.020097210698210.000007295
0x0c4717e27c08eac27aa577e5257ef9ebcb74160184ac9064240f06b492f60726Expire Markets228417042021-01-01 11:51:20137 days 9 hrs ago0x57170b6ae91d06102ec7d984d551d590ce1504e5 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.00002815471.05
0xab0c653613363fd3ecbd9c6fd8f4340267faaa943051826f74bed571753b6699Expire Markets228410492021-01-01 10:37:00137 days 10 hrs ago0xdf0b4944f09807b6cd38afd33169cce1364acacf IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.0000249381
0x2656324aea0dbbe4889bc3bc39d15016ff5e77ffaf08417aab8b07ee0ea39b66Expire Markets228379742021-01-01 4:42:12137 days 16 hrs ago0xe51a50e95c5a92cb4650eacf6ffcb3eb25c7a012 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.0000821781
0x89335b1bf839110c925680fdcb956c2634fc82538c5d0252e6f47e438670b95eSet Migrating Ma...227362362020-12-24 6:01:00145 days 14 hrs ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.0001214055
0xbe48d7d36f3ec29951be0aee464c4375b8260be3c32274783c211bbf54f6cf22Set Migrating Ma...227362302020-12-24 6:00:20145 days 14 hrs ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.0001214055
0x60ff5fb4a2abe6b6944c29e874d5cee08c19dd728155059957790cea58a9aa49Set Migrating Ma...227362092020-12-24 5:58:00145 days 14 hrs ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.0001214055
0xd69929f78c499ef8a0bf7a473e7c92d20809e44b93ed73bcb060aa9b8e6e60c4Set Migrating Ma...227361382020-12-24 5:49:52145 days 15 hrs ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f0 Ether0.0001214055
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x98d0ed29e5481f22a75ae1131d4deefaab3c452b62832bfe2b4e219c3081e2f5248081662021-05-13 4:55:205 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x2e5af9ce18bd674c803a5f34f25b917018ad48590 Ether
0x98d0ed29e5481f22a75ae1131d4deefaab3c452b62832bfe2b4e219c3081e2f5248081662021-05-13 4:55:205 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x2e5af9ce18bd674c803a5f34f25b917018ad48590 Ether
0x98d0ed29e5481f22a75ae1131d4deefaab3c452b62832bfe2b4e219c3081e2f5248081662021-05-13 4:55:205 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0xb40fc3beb4a4e1d3fc50d00307e55a32c2542bd60 Ether
0x98d0ed29e5481f22a75ae1131d4deefaab3c452b62832bfe2b4e219c3081e2f5248081662021-05-13 4:55:205 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0xb40fc3beb4a4e1d3fc50d00307e55a32c2542bd60 Ether
0x98d0ed29e5481f22a75ae1131d4deefaab3c452b62832bfe2b4e219c3081e2f5248081662021-05-13 4:55:205 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0xf8ac07609d933bb5863cbf52a508dd6a2cb571c50 Ether
0x98d0ed29e5481f22a75ae1131d4deefaab3c452b62832bfe2b4e219c3081e2f5248081662021-05-13 4:55:205 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0xf8ac07609d933bb5863cbf52a508dd6a2cb571c50 Ether
0x98d0ed29e5481f22a75ae1131d4deefaab3c452b62832bfe2b4e219c3081e2f5248081662021-05-13 4:55:205 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x2c5d2606e18eb436431c5c603765639dd568cbc70 Ether
0x98d0ed29e5481f22a75ae1131d4deefaab3c452b62832bfe2b4e219c3081e2f5248081662021-05-13 4:55:205 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x2c5d2606e18eb436431c5c603765639dd568cbc70 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x0e5c40302b4d2b256a1081f0dc9ab488b149b5b90 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x0e5c40302b4d2b256a1081f0dc9ab488b149b5b90 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x0900f0c02270805f0b497d183d8b1b54beb2601f0 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x0900f0c02270805f0b497d183d8b1b54beb2601f0 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x79eeeb3a2e144b42ea31d1aff43cd73bd12667360 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x79eeeb3a2e144b42ea31d1aff43cd73bd12667360 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0xc88bf57adb02020a9a7212f47ef2dd5d7556037b0 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0xbed77ce29399ebc63ac243a02926916bc5344c560 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x3314648a222e80e34519161f6b0943304bb755c90 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0xf149e33d3fc45d6336e7eb7a4ecc63425e85b01f0 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x6bd2567a4880a286795102b19a71dd6e83bd70660 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x6dff5db48fc6844c607ce9fbd2f6e511844914800 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x6dff5db48fc6844c607ce9fbd2f6e511844914800 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x1ef7ffec22dc0263ad612f08857420f5d691d7540 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0x1ef7ffec22dc0263ad612f08857420f5d691d7540 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0xb1d8512864732a3d3096c9175b18703cbb1cd24e0 Ether
0xf5612ae799e152f447e5996de1c60e8c51b3f9a0bfadbd00b084e1926fc3a916248081642021-05-13 4:55:085 days 16 hrs ago 0x95dcaddaa40ac726bf4734754e6b75eae6f5eb9f 0xb1d8512864732a3d3096c9175b18703cbb1cd24e0 Ether
[ Download CSV Export 
Loading

Contract Source Code Verified (Similar Match)
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0xB9c720Aec5680d8022Dd4c4e89a3a3C1995b4197

Contract Name:
BinaryOptionMarketManager

Compiler Version
v0.5.16+commit.9c3226ce

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-12-21
*/

/*
   ____            __   __        __   _
  / __/__ __ ___  / /_ / /  ___  / /_ (_)__ __
 _\ \ / // // _ \/ __// _ \/ -_)/ __// / \ \ /
/___/ \_, //_//_/\__//_//_/\__/ \__//_/ /_\_\
     /___/

* Synthetix: BinaryOptionMarketManager.sol
*
* Latest source (may be newer): https://github.com/Synthetixio/synthetix/blob/master/contracts/BinaryOptionMarketManager.sol
* Docs: https://docs.synthetix.io/contracts/BinaryOptionMarketManager
*
* Contract Dependencies: 
*	- IAddressResolver
*	- IBinaryOption
*	- IBinaryOptionMarket
*	- IBinaryOptionMarketManager
*	- IERC20
*	- MixinResolver
*	- Owned
*	- Pausable
* Libraries: 
*	- AddressSetLib
*	- SafeDecimalMath
*	- SafeMath
*
* MIT License
* ===========
*
* Copyright (c) 2020 Synthetix
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
*/



pragma solidity ^0.5.16;


// https://docs.synthetix.io/contracts/source/contracts/owned
contract Owned {
    address public owner;
    address public nominatedOwner;

    constructor(address _owner) public {
        require(_owner != address(0), "Owner address cannot be 0");
        owner = _owner;
        emit OwnerChanged(address(0), _owner);
    }

    function nominateNewOwner(address _owner) external onlyOwner {
        nominatedOwner = _owner;
        emit OwnerNominated(_owner);
    }

    function acceptOwnership() external {
        require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
        emit OwnerChanged(owner, nominatedOwner);
        owner = nominatedOwner;
        nominatedOwner = address(0);
    }

    modifier onlyOwner {
        _onlyOwner();
        _;
    }

    function _onlyOwner() private view {
        require(msg.sender == owner, "Only the contract owner may perform this action");
    }

    event OwnerNominated(address newOwner);
    event OwnerChanged(address oldOwner, address newOwner);
}


// Inheritance


// https://docs.synthetix.io/contracts/source/contracts/pausable
contract Pausable is Owned {
    uint public lastPauseTime;
    bool public paused;

    constructor() internal {
        // This contract is abstract, and thus cannot be instantiated directly
        require(owner != address(0), "Owner must be set");
        // Paused will be false, and lastPauseTime will be 0 upon initialisation
    }

    /**
     * @notice Change the paused state of the contract
     * @dev Only the contract owner may call this.
     */
    function setPaused(bool _paused) external onlyOwner {
        // Ensure we're actually changing the state before we do anything
        if (_paused == paused) {
            return;
        }

        // Set our paused state.
        paused = _paused;

        // If applicable, set the last pause time.
        if (paused) {
            lastPauseTime = now;
        }

        // Let everyone know that our pause state has changed.
        emit PauseChanged(paused);
    }

    event PauseChanged(bool isPaused);

    modifier notPaused {
        require(!paused, "This action cannot be performed while the contract is paused");
        _;
    }
}


// https://docs.synthetix.io/contracts/source/interfaces/iaddressresolver
interface IAddressResolver {
    function getAddress(bytes32 name) external view returns (address);

    function getSynth(bytes32 key) external view returns (address);

    function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address);
}


// https://docs.synthetix.io/contracts/source/interfaces/isynth
interface ISynth {
    // Views
    function currencyKey() external view returns (bytes32);

    function transferableSynths(address account) external view returns (uint);

    // Mutative functions
    function transferAndSettle(address to, uint value) external returns (bool);

    function transferFromAndSettle(
        address from,
        address to,
        uint value
    ) external returns (bool);

    // Restricted: used internally to Synthetix
    function burn(address account, uint amount) external;

    function issue(address account, uint amount) external;
}


// https://docs.synthetix.io/contracts/source/interfaces/iissuer
interface IIssuer {
    // Views
    function anySynthOrSNXRateIsInvalid() external view returns (bool anyRateInvalid);

    function availableCurrencyKeys() external view returns (bytes32[] memory);

    function availableSynthCount() external view returns (uint);

    function availableSynths(uint index) external view returns (ISynth);

    function canBurnSynths(address account) external view returns (bool);

    function collateral(address account) external view returns (uint);

    function collateralisationRatio(address issuer) external view returns (uint);

    function collateralisationRatioAndAnyRatesInvalid(address _issuer)
        external
        view
        returns (uint cratio, bool anyRateIsInvalid);

    function debtBalanceOf(address issuer, bytes32 currencyKey) external view returns (uint debtBalance);

    function issuanceRatio() external view returns (uint);

    function lastIssueEvent(address account) external view returns (uint);

    function maxIssuableSynths(address issuer) external view returns (uint maxIssuable);

    function minimumStakeTime() external view returns (uint);

    function remainingIssuableSynths(address issuer)
        external
        view
        returns (
            uint maxIssuable,
            uint alreadyIssued,
            uint totalSystemDebt
        );

    function synths(bytes32 currencyKey) external view returns (ISynth);

    function getSynths(bytes32[] calldata currencyKeys) external view returns (ISynth[] memory);

    function synthsByAddress(address synthAddress) external view returns (bytes32);

    function totalIssuedSynths(bytes32 currencyKey, bool excludeEtherCollateral) external view returns (uint);

    function transferableSynthetixAndAnyRateIsInvalid(address account, uint balance)
        external
        view
        returns (uint transferable, bool anyRateIsInvalid);

    // Restricted: used internally to Synthetix
    function issueSynths(address from, uint amount) external;

    function issueSynthsOnBehalf(
        address issueFor,
        address from,
        uint amount
    ) external;

    function issueMaxSynths(address from) external;

    function issueMaxSynthsOnBehalf(address issueFor, address from) external;

    function burnSynths(address from, uint amount) external;

    function burnSynthsOnBehalf(
        address burnForAddress,
        address from,
        uint amount
    ) external;

    function burnSynthsToTarget(address from) external;

    function burnSynthsToTargetOnBehalf(address burnForAddress, address from) external;

    function liquidateDelinquentAccount(
        address account,
        uint susdAmount,
        address liquidator
    ) external returns (uint totalRedeemed, uint amountToLiquidate);
}


// Inheritance


// Internal references


// https://docs.synthetix.io/contracts/source/contracts/addressresolver
contract AddressResolver is Owned, IAddressResolver {
    mapping(bytes32 => address) public repository;

    constructor(address _owner) public Owned(_owner) {}

    /* ========== RESTRICTED FUNCTIONS ========== */

    function importAddresses(bytes32[] calldata names, address[] calldata destinations) external onlyOwner {
        require(names.length == destinations.length, "Input lengths must match");

        for (uint i = 0; i < names.length; i++) {
            bytes32 name = names[i];
            address destination = destinations[i];
            repository[name] = destination;
            emit AddressImported(name, destination);
        }
    }

    /* ========= PUBLIC FUNCTIONS ========== */

    function rebuildCaches(MixinResolver[] calldata destinations) external {
        for (uint i = 0; i < destinations.length; i++) {
            destinations[i].rebuildCache();
        }
    }

    /* ========== VIEWS ========== */

    function areAddressesImported(bytes32[] calldata names, address[] calldata destinations) external view returns (bool) {
        for (uint i = 0; i < names.length; i++) {
            if (repository[names[i]] != destinations[i]) {
                return false;
            }
        }
        return true;
    }

    function getAddress(bytes32 name) external view returns (address) {
        return repository[name];
    }

    function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address) {
        address _foundAddress = repository[name];
        require(_foundAddress != address(0), reason);
        return _foundAddress;
    }

    function getSynth(bytes32 key) external view returns (address) {
        IIssuer issuer = IIssuer(repository["Issuer"]);
        require(address(issuer) != address(0), "Cannot find Issuer address");
        return address(issuer.synths(key));
    }

    /* ========== EVENTS ========== */

    event AddressImported(bytes32 name, address destination);
}


// solhint-disable payable-fallback

// https://docs.synthetix.io/contracts/source/contracts/readproxy
contract ReadProxy is Owned {
    address public target;

    constructor(address _owner) public Owned(_owner) {}

    function setTarget(address _target) external onlyOwner {
        target = _target;
        emit TargetUpdated(target);
    }

    function() external {
        // The basics of a proxy read call
        // Note that msg.sender in the underlying will always be the address of this contract.
        assembly {
            calldatacopy(0, 0, calldatasize)

            // Use of staticcall - this will revert if the underlying function mutates state
            let result := staticcall(gas, sload(target_slot), 0, calldatasize, 0, 0)
            returndatacopy(0, 0, returndatasize)

            if iszero(result) {
                revert(0, returndatasize)
            }
            return(0, returndatasize)
        }
    }

    event TargetUpdated(address newTarget);
}


// Inheritance


// Internal references


// https://docs.synthetix.io/contracts/source/contracts/mixinresolver
contract MixinResolver {
    AddressResolver public resolver;

    mapping(bytes32 => address) private addressCache;

    constructor(address _resolver) internal {
        resolver = AddressResolver(_resolver);
    }

    /* ========== INTERNAL FUNCTIONS ========== */

    function combineArrays(bytes32[] memory first, bytes32[] memory second)
        internal
        pure
        returns (bytes32[] memory combination)
    {
        combination = new bytes32[](first.length + second.length);

        for (uint i = 0; i < first.length; i++) {
            combination[i] = first[i];
        }

        for (uint j = 0; j < second.length; j++) {
            combination[first.length + j] = second[j];
        }
    }

    /* ========== PUBLIC FUNCTIONS ========== */

    // Note: this function is public not external in order for it to be overridden and invoked via super in subclasses
    function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {}

    function rebuildCache() external {
        bytes32[] memory requiredAddresses = resolverAddressesRequired();
        // The resolver must call this function whenver it updates its state
        for (uint i = 0; i < requiredAddresses.length; i++) {
            bytes32 name = requiredAddresses[i];
            // Note: can only be invoked once the resolver has all the targets needed added
            address destination = resolver.requireAndGetAddress(
                name,
                string(abi.encodePacked("Resolver missing target: ", name))
            );
            addressCache[name] = destination;
            emit CacheUpdated(name, destination);
        }
    }

    /* ========== VIEWS ========== */

    function isResolverCached() external view returns (bool) {
        bytes32[] memory requiredAddresses = resolverAddressesRequired();
        for (uint i = 0; i < requiredAddresses.length; i++) {
            bytes32 name = requiredAddresses[i];
            // false if our cache is invalid or if the resolver doesn't have the required address
            if (resolver.getAddress(name) != addressCache[name] || addressCache[name] == address(0)) {
                return false;
            }
        }

        return true;
    }

    /* ========== INTERNAL FUNCTIONS ========== */

    function requireAndGetAddress(bytes32 name) internal view returns (address) {
        address _foundAddress = addressCache[name];
        require(_foundAddress != address(0), string(abi.encodePacked("Missing address: ", name)));
        return _foundAddress;
    }

    /* ========== EVENTS ========== */

    event CacheUpdated(bytes32 name, address destination);
}


// https://docs.synthetix.io/contracts/source/interfaces/ierc20
interface IERC20 {
    // ERC20 Optional Views
    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);

    // Views
    function totalSupply() external view returns (uint);

    function balanceOf(address owner) external view returns (uint);

    function allowance(address owner, address spender) external view returns (uint);

    // Mutative functions
    function transfer(address to, uint value) external returns (bool);

    function approve(address spender, uint value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint value
    ) external returns (bool);

    // Events
    event Transfer(address indexed from, address indexed to, uint value);

    event Approval(address indexed owner, address indexed spender, uint value);
}


// https://docs.synthetix.io/contracts/source/interfaces/ibinaryoption
interface IBinaryOption {
    /* ========== VIEWS / VARIABLES ========== */

    function market() external view returns (IBinaryOptionMarket);

    function bidOf(address account) external view returns (uint);

    function totalBids() external view returns (uint);

    function balanceOf(address account) external view returns (uint);

    function totalSupply() external view returns (uint);

    function claimableBalanceOf(address account) external view returns (uint);

    function totalClaimableSupply() external view returns (uint);
}


// https://docs.synthetix.io/contracts/source/interfaces/ibinaryoptionmarket
interface IBinaryOptionMarket {
    /* ========== TYPES ========== */

    enum Phase {Bidding, Trading, Maturity, Expiry}
    enum Side {Long, Short}

    /* ========== VIEWS / VARIABLES ========== */

    function options() external view returns (IBinaryOption long, IBinaryOption short);

    function prices() external view returns (uint long, uint short);

    function times()
        external
        view
        returns (
            uint biddingEnd,
            uint maturity,
            uint destructino
        );

    function oracleDetails()
        external
        view
        returns (
            bytes32 key,
            uint strikePrice,
            uint finalPrice
        );

    function fees()
        external
        view
        returns (
            uint poolFee,
            uint creatorFee,
            uint refundFee
        );

    function creatorLimits() external view returns (uint capitalRequirement, uint skewLimit);

    function deposited() external view returns (uint);

    function creator() external view returns (address);

    function resolved() external view returns (bool);

    function refundsEnabled() external view returns (bool);

    function phase() external view returns (Phase);

    function oraclePriceAndTimestamp() external view returns (uint price, uint updatedAt);

    function canResolve() external view returns (bool);

    function result() external view returns (Side);

    function pricesAfterBidOrRefund(
        Side side,
        uint value,
        bool refund
    ) external view returns (uint long, uint short);

    function bidOrRefundForPrice(
        Side bidSide,
        Side priceSide,
        uint price,
        bool refund
    ) external view returns (uint);

    function bidsOf(address account) external view returns (uint long, uint short);

    function totalBids() external view returns (uint long, uint short);

    function claimableBalancesOf(address account) external view returns (uint long, uint short);

    function totalClaimableSupplies() external view returns (uint long, uint short);

    function balancesOf(address account) external view returns (uint long, uint short);

    function totalSupplies() external view returns (uint long, uint short);

    function exercisableDeposits() external view returns (uint);

    /* ========== MUTATIVE FUNCTIONS ========== */

    function bid(Side side, uint value) external;

    function refund(Side side, uint value) external returns (uint refundMinusFee);

    function claimOptions() external returns (uint longClaimed, uint shortClaimed);

    function exerciseOptions() external returns (uint);
}


// https://docs.synthetix.io/contracts/source/interfaces/ibinaryoptionmarketmanager
interface IBinaryOptionMarketManager {
    /* ========== VIEWS / VARIABLES ========== */

    function fees()
        external
        view
        returns (
            uint poolFee,
            uint creatorFee,
            uint refundFee
        );

    function durations()
        external
        view
        returns (
            uint maxOraclePriceAge,
            uint expiryDuration,
            uint maxTimeToMaturity
        );

    function creatorLimits() external view returns (uint capitalRequirement, uint skewLimit);

    function marketCreationEnabled() external view returns (bool);

    function totalDeposited() external view returns (uint);

    function numActiveMarkets() external view returns (uint);

    function activeMarkets(uint index, uint pageSize) external view returns (address[] memory);

    function numMaturedMarkets() external view returns (uint);

    function maturedMarkets(uint index, uint pageSize) external view returns (address[] memory);

    /* ========== MUTATIVE FUNCTIONS ========== */

    function createMarket(
        bytes32 oracleKey,
        uint strikePrice,
        bool refundsEnabled,
        uint[2] calldata times, // [biddingEnd, maturity]
        uint[2] calldata bids // [longBid, shortBid]
    ) external returns (IBinaryOptionMarket);

    function resolveMarket(address market) external;

    function cancelMarket(address market) external;

    function expireMarkets(address[] calldata market) external;
}


// https://docs.synthetix.io/contracts/source/libraries/addresssetlib/
library AddressSetLib {
    struct AddressSet {
        address[] elements;
        mapping(address => uint) indices;
    }

    function contains(AddressSet storage set, address candidate) internal view returns (bool) {
        if (set.elements.length == 0) {
            return false;
        }
        uint index = set.indices[candidate];
        return index != 0 || set.elements[0] == candidate;
    }

    function getPage(
        AddressSet storage set,
        uint index,
        uint pageSize
    ) internal view returns (address[] memory) {
        // NOTE: This implementation should be converted to slice operators if the compiler is updated to v0.6.0+
        uint endIndex = index + pageSize; // The check below that endIndex <= index handles overflow.

        // If the page extends past the end of the list, truncate it.
        if (endIndex > set.elements.length) {
            endIndex = set.elements.length;
        }
        if (endIndex <= index) {
            return new address[](0);
        }

        uint n = endIndex - index; // We already checked for negative overflow.
        address[] memory page = new address[](n);
        for (uint i; i < n; i++) {
            page[i] = set.elements[i + index];
        }
        return page;
    }

    function add(AddressSet storage set, address element) internal {
        // Adding to a set is an idempotent operation.
        if (!contains(set, element)) {
            set.indices[element] = set.elements.length;
            set.elements.push(element);
        }
    }

    function remove(AddressSet storage set, address element) internal {
        require(contains(set, element), "Element not in set.");
        // Replace the removed element with the last element of the list.
        uint index = set.indices[element];
        uint lastIndex = set.elements.length - 1; // We required that element is in the list, so it is not empty.
        if (index != lastIndex) {
            // No need to shift the last element if it is the one we want to delete.
            address shiftedElement = set.elements[lastIndex];
            set.elements[index] = shiftedElement;
            set.indices[shiftedElement] = index;
        }
        set.elements.pop();
        delete set.indices[element];
    }
}


/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;
    }
}


// Libraries


// https://docs.synthetix.io/contracts/source/libraries/safedecimalmath
library SafeDecimalMath {
    using SafeMath for uint;

    /* Number of decimal places in the representations. */
    uint8 public constant decimals = 18;
    uint8 public constant highPrecisionDecimals = 27;

    /* The number representing 1.0. */
    uint public constant UNIT = 10**uint(decimals);

    /* The number representing 1.0 for higher fidelity numbers. */
    uint public constant PRECISE_UNIT = 10**uint(highPrecisionDecimals);
    uint private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR = 10**uint(highPrecisionDecimals - decimals);

    /**
     * @return Provides an interface to UNIT.
     */
    function unit() external pure returns (uint) {
        return UNIT;
    }

    /**
     * @return Provides an interface to PRECISE_UNIT.
     */
    function preciseUnit() external pure returns (uint) {
        return PRECISE_UNIT;
    }

    /**
     * @return The result of multiplying x and y, interpreting the operands as fixed-point
     * decimals.
     *
     * @dev A unit factor is divided out after the product of x and y is evaluated,
     * so that product must be less than 2**256. As this is an integer division,
     * the internal division always rounds down. This helps save on gas. Rounding
     * is more expensive on gas.
     */
    function multiplyDecimal(uint x, uint y) internal pure returns (uint) {
        /* Divide by UNIT to remove the extra factor introduced by the product. */
        return x.mul(y) / UNIT;
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of the specified precision unit.
     *
     * @dev The operands should be in the form of a the specified unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function _multiplyDecimalRound(
        uint x,
        uint y,
        uint precisionUnit
    ) private pure returns (uint) {
        /* Divide by UNIT to remove the extra factor introduced by the product. */
        uint quotientTimesTen = x.mul(y) / (precisionUnit / 10);

        if (quotientTimesTen % 10 >= 5) {
            quotientTimesTen += 10;
        }

        return quotientTimesTen / 10;
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of a precise unit.
     *
     * @dev The operands should be in the precise unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function multiplyDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) {
        return _multiplyDecimalRound(x, y, PRECISE_UNIT);
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of a standard unit.
     *
     * @dev The operands should be in the standard unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function multiplyDecimalRound(uint x, uint y) internal pure returns (uint) {
        return _multiplyDecimalRound(x, y, UNIT);
    }

    /**
     * @return The result of safely dividing x and y. The return value is a high
     * precision decimal.
     *
     * @dev y is divided after the product of x and the standard precision unit
     * is evaluated, so the product of x and UNIT must be less than 2**256. As
     * this is an integer division, the result is always rounded down.
     * This helps save on gas. Rounding is more expensive on gas.
     */
    function divideDecimal(uint x, uint y) internal pure returns (uint) {
        /* Reintroduce the UNIT factor that will be divided out by y. */
        return x.mul(UNIT).div(y);
    }

    /**
     * @return The result of safely dividing x and y. The return value is as a rounded
     * decimal in the precision unit specified in the parameter.
     *
     * @dev y is divided after the product of x and the specified precision unit
     * is evaluated, so the product of x and the specified precision unit must
     * be less than 2**256. The result is rounded to the nearest increment.
     */
    function _divideDecimalRound(
        uint x,
        uint y,
        uint precisionUnit
    ) private pure returns (uint) {
        uint resultTimesTen = x.mul(precisionUnit * 10).div(y);

        if (resultTimesTen % 10 >= 5) {
            resultTimesTen += 10;
        }

        return resultTimesTen / 10;
    }

    /**
     * @return The result of safely dividing x and y. The return value is as a rounded
     * standard precision decimal.
     *
     * @dev y is divided after the product of x and the standard precision unit
     * is evaluated, so the product of x and the standard precision unit must
     * be less than 2**256. The result is rounded to the nearest increment.
     */
    function divideDecimalRound(uint x, uint y) internal pure returns (uint) {
        return _divideDecimalRound(x, y, UNIT);
    }

    /**
     * @return The result of safely dividing x and y. The return value is as a rounded
     * high precision decimal.
     *
     * @dev y is divided after the product of x and the high precision unit
     * is evaluated, so the product of x and the high precision unit must
     * be less than 2**256. The result is rounded to the nearest increment.
     */
    function divideDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) {
        return _divideDecimalRound(x, y, PRECISE_UNIT);
    }

    /**
     * @dev Convert a standard decimal representation to a high precision one.
     */
    function decimalToPreciseDecimal(uint i) internal pure returns (uint) {
        return i.mul(UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR);
    }

    /**
     * @dev Convert a high precision decimal to a standard decimal representation.
     */
    function preciseDecimalToDecimal(uint i) internal pure returns (uint) {
        uint quotientTimesTen = i / (UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR / 10);

        if (quotientTimesTen % 10 >= 5) {
            quotientTimesTen += 10;
        }

        return quotientTimesTen / 10;
    }
}


// Inheritance


// Libraries


// Internal references


// https://docs.synthetix.io/contracts/source/contracts/binaryoption
contract BinaryOption is IERC20, IBinaryOption {
    /* ========== LIBRARIES ========== */

    using SafeMath for uint;
    using SafeDecimalMath for uint;

    /* ========== STATE VARIABLES ========== */

    string public constant name = "SNX Binary Option";
    string public constant symbol = "sOPT";
    uint8 public constant decimals = 18;

    BinaryOptionMarket public market;

    mapping(address => uint) public bidOf;
    uint public totalBids;

    mapping(address => uint) public balanceOf;
    uint public totalSupply;

    // The argument order is allowance[owner][spender]
    mapping(address => mapping(address => uint)) public allowance;

    // Enforce a 1 cent minimum bid balance
    uint internal constant _MINIMUM_BID = 1e16;

    /* ========== CONSTRUCTOR ========== */

    constructor(address initialBidder, uint initialBid) public {
        market = BinaryOptionMarket(msg.sender);
        bidOf[initialBidder] = initialBid;
        totalBids = initialBid;
    }

    /* ========== VIEWS ========== */

    function _claimableBalanceOf(
        uint _bid,
        uint price,
        uint exercisableDeposits
    ) internal view returns (uint) {
        uint owed = _bid.divideDecimal(price);
        uint supply = _totalClaimableSupply(exercisableDeposits);

        /* The last claimant might be owed slightly more or less than the actual remaining deposit
           based on rounding errors with the price.
           Therefore if the user's bid is the entire rest of the pot, just give them everything that's left.
           If there is no supply, then this option lost, and we'll return 0.
           */
        if ((_bid == totalBids && _bid != 0) || supply == 0) {
            return supply;
        }

        /* Note that option supply on the losing side and deposits can become decoupled,
           but losing options are not claimable, therefore we only need to worry about
           the situation where supply < owed on the winning side.

           If somehow a user who is not the last bidder is owed more than what's available,
           subsequent bidders will be disadvantaged. Given that the minimum bid is 10^16 wei,
           this should never occur in reality. */
        require(owed <= supply, "supply < claimable");
        return owed;
    }

    function claimableBalanceOf(address account) external view returns (uint) {
        (uint price, uint exercisableDeposits) = market.senderPriceAndExercisableDeposits();
        return _claimableBalanceOf(bidOf[account], price, exercisableDeposits);
    }

    function _totalClaimableSupply(uint exercisableDeposits) internal view returns (uint) {
        uint _totalSupply = totalSupply;
        // We'll avoid throwing an exception here to avoid breaking any dapps, but this case
        // should never occur given the minimum bid size.
        if (exercisableDeposits <= _totalSupply) {
            return 0;
        }
        return exercisableDeposits.sub(_totalSupply);
    }

    function totalClaimableSupply() external view returns (uint) {
        (, uint exercisableDeposits) = market.senderPriceAndExercisableDeposits();
        return _totalClaimableSupply(exercisableDeposits);
    }

    /* ========== MUTATIVE FUNCTIONS ========== */

    function _requireMinimumBid(uint bid) internal pure returns (uint) {
        require(bid >= _MINIMUM_BID || bid == 0, "Balance < $0.01");
        return bid;
    }

    // This must only be invoked during bidding.
    function bid(address bidder, uint newBid) external onlyMarket {
        bidOf[bidder] = _requireMinimumBid(bidOf[bidder].add(newBid));
        totalBids = totalBids.add(newBid);
    }

    // This must only be invoked during bidding.
    function refund(address bidder, uint newRefund) external onlyMarket {
        // The safe subtraction will catch refunds that are too large.
        bidOf[bidder] = _requireMinimumBid(bidOf[bidder].sub(newRefund));
        totalBids = totalBids.sub(newRefund);
    }

    // This must only be invoked after bidding.
    function claim(
        address claimant,
        uint price,
        uint depositsRemaining
    ) external onlyMarket returns (uint optionsClaimed) {
        uint _bid = bidOf[claimant];
        uint claimable = _claimableBalanceOf(_bid, price, depositsRemaining);
        // No options to claim? Nothing happens.
        if (claimable == 0) {
            return 0;
        }

        totalBids = totalBids.sub(_bid);
        bidOf[claimant] = 0;

        totalSupply = totalSupply.add(claimable);
        balanceOf[claimant] = balanceOf[claimant].add(claimable); // Increment rather than assigning since a transfer may have occurred.

        emit Transfer(address(0), claimant, claimable);
        emit Issued(claimant, claimable);

        return claimable;
    }

    // This must only be invoked after maturity.
    function exercise(address claimant) external onlyMarket {
        uint balance = balanceOf[claimant];

        if (balance == 0) {
            return;
        }

        balanceOf[claimant] = 0;
        totalSupply = totalSupply.sub(balance);

        emit Transfer(claimant, address(0), balance);
        emit Burned(claimant, balance);
    }

    // This must only be invoked after the exercise window is complete.
    // Note that any options which have not been exercised will linger.
    function expire(address payable beneficiary) external onlyMarket {
        selfdestruct(beneficiary);
    }

    /* ---------- ERC20 Functions ---------- */

    // This should only operate after bidding;
    // Since options can't be claimed until after bidding, all balances are zero until that time.
    // So we don't need to explicitly check the timestamp to prevent transfers.
    function _transfer(
        address _from,
        address _to,
        uint _value
    ) internal returns (bool success) {
        market.requireActiveAndUnpaused();
        require(_to != address(0) && _to != address(this), "Invalid address");

        uint fromBalance = balanceOf[_from];
        require(_value <= fromBalance, "Insufficient balance");

        balanceOf[_from] = fromBalance.sub(_value);
        balanceOf[_to] = balanceOf[_to].add(_value);

        emit Transfer(_from, _to, _value);
        return true;
    }

    function transfer(address _to, uint _value) external returns (bool success) {
        return _transfer(msg.sender, _to, _value);
    }

    function transferFrom(
        address _from,
        address _to,
        uint _value
    ) external returns (bool success) {
        uint fromAllowance = allowance[_from][msg.sender];
        require(_value <= fromAllowance, "Insufficient allowance");

        allowance[_from][msg.sender] = fromAllowance.sub(_value);
        return _transfer(_from, _to, _value);
    }

    function approve(address _spender, uint _value) external returns (bool success) {
        require(_spender != address(0));
        allowance[msg.sender][_spender] = _value;
        emit Approval(msg.sender, _spender, _value);
        return true;
    }

    /* ========== MODIFIERS ========== */

    modifier onlyMarket() {
        require(msg.sender == address(market), "Only market allowed");
        _;
    }

    /* ========== EVENTS ========== */

    event Issued(address indexed account, uint value);
    event Burned(address indexed account, uint value);
    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
}


// https://docs.synthetix.io/contracts/source/interfaces/iexchangerates
interface IExchangeRates {
    // Structs
    struct RateAndUpdatedTime {
        uint216 rate;
        uint40 time;
    }

    struct InversePricing {
        uint entryPoint;
        uint upperLimit;
        uint lowerLimit;
        bool frozenAtUpperLimit;
        bool frozenAtLowerLimit;
    }

    // Views
    function aggregators(bytes32 currencyKey) external view returns (address);

    function aggregatorWarningFlags() external view returns (address);

    function anyRateIsInvalid(bytes32[] calldata currencyKeys) external view returns (bool);

    function canFreezeRate(bytes32 currencyKey) external view returns (bool);

    function currentRoundForRate(bytes32 currencyKey) external view returns (uint);

    function currenciesUsingAggregator(address aggregator) external view returns (bytes32[] memory);

    function effectiveValue(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey
    ) external view returns (uint value);

    function effectiveValueAndRates(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey
    )
        external
        view
        returns (
            uint value,
            uint sourceRate,
            uint destinationRate
        );

    function effectiveValueAtRound(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        uint roundIdForSrc,
        uint roundIdForDest
    ) external view returns (uint value);

    function getCurrentRoundId(bytes32 currencyKey) external view returns (uint);

    function getLastRoundIdBeforeElapsedSecs(
        bytes32 currencyKey,
        uint startingRoundId,
        uint startingTimestamp,
        uint timediff
    ) external view returns (uint);

    function inversePricing(bytes32 currencyKey)
        external
        view
        returns (
            uint entryPoint,
            uint upperLimit,
            uint lowerLimit,
            bool frozenAtUpperLimit,
            bool frozenAtLowerLimit
        );

    function lastRateUpdateTimes(bytes32 currencyKey) external view returns (uint256);

    function oracle() external view returns (address);

    function rateAndTimestampAtRound(bytes32 currencyKey, uint roundId) external view returns (uint rate, uint time);

    function rateAndUpdatedTime(bytes32 currencyKey) external view returns (uint rate, uint time);

    function rateAndInvalid(bytes32 currencyKey) external view returns (uint rate, bool isInvalid);

    function rateForCurrency(bytes32 currencyKey) external view returns (uint);

    function rateIsFlagged(bytes32 currencyKey) external view returns (bool);

    function rateIsFrozen(bytes32 currencyKey) external view returns (bool);

    function rateIsInvalid(bytes32 currencyKey) external view returns (bool);

    function rateIsStale(bytes32 currencyKey) external view returns (bool);

    function rateStalePeriod() external view returns (uint);

    function ratesAndUpdatedTimeForCurrencyLastNRounds(bytes32 currencyKey, uint numRounds)
        external
        view
        returns (uint[] memory rates, uint[] memory times);

    function ratesAndInvalidForCurrencies(bytes32[] calldata currencyKeys)
        external
        view
        returns (uint[] memory rates, bool anyRateInvalid);

    function ratesForCurrencies(bytes32[] calldata currencyKeys) external view returns (uint[] memory);

    // Mutative functions
    function freezeRate(bytes32 currencyKey) external;
}


// https://docs.synthetix.io/contracts/source/interfaces/ifeepool
interface IFeePool {
    // Views

    // solhint-disable-next-line func-name-mixedcase
    function FEE_ADDRESS() external view returns (address);

    function feesAvailable(address account) external view returns (uint, uint);

    function feePeriodDuration() external view returns (uint);

    function isFeesClaimable(address account) external view returns (bool);

    function targetThreshold() external view returns (uint);

    function totalFeesAvailable() external view returns (uint);

    function totalRewardsAvailable() external view returns (uint);

    // Mutative Functions
    function claimFees() external returns (bool);

    function claimOnBehalf(address claimingForAddress) external returns (bool);

    function closeCurrentFeePeriod() external;

    // Restricted: used internally to Synthetix
    function appendAccountIssuanceRecord(
        address account,
        uint lockedAmount,
        uint debtEntryIndex
    ) external;

    function recordFeePaid(uint sUSDAmount) external;

    function setRewardsToDistribute(uint amount) external;
}


// Inheritance


// Libraries


// Internal references


// https://docs.synthetix.io/contracts/source/contracts/binaryoptionmarket
contract BinaryOptionMarket is Owned, MixinResolver, IBinaryOptionMarket {
    /* ========== LIBRARIES ========== */

    using SafeMath for uint;
    using SafeDecimalMath for uint;

    /* ========== TYPES ========== */

    struct Options {
        BinaryOption long;
        BinaryOption short;
    }

    struct Prices {
        uint long;
        uint short;
    }

    struct Times {
        uint biddingEnd;
        uint maturity;
        uint expiry;
    }

    struct OracleDetails {
        bytes32 key;
        uint strikePrice;
        uint finalPrice;
    }

    /* ========== STATE VARIABLES ========== */

    Options public options;
    Prices public prices;
    Times public times;
    OracleDetails public oracleDetails;
    BinaryOptionMarketManager.Fees public fees;
    BinaryOptionMarketManager.CreatorLimits public creatorLimits;

    // `deposited` tracks the sum of open bids on short and long, plus withheld refund fees.
    // This must explicitly be kept, in case tokens are transferred to the contract directly.
    uint public deposited;
    address public creator;
    bool public resolved;
    bool public refundsEnabled;

    uint internal _feeMultiplier;

    /* ---------- Address Resolver Configuration ---------- */

    bytes32 internal constant CONTRACT_SYSTEMSTATUS = "SystemStatus";
    bytes32 internal constant CONTRACT_EXRATES = "ExchangeRates";
    bytes32 internal constant CONTRACT_SYNTHSUSD = "SynthsUSD";
    bytes32 internal constant CONTRACT_FEEPOOL = "FeePool";

    /* ========== CONSTRUCTOR ========== */

    constructor(
        address _owner,
        address _creator,
        address _resolver,
        uint[2] memory _creatorLimits, // [capitalRequirement, skewLimit]
        bytes32 _oracleKey,
        uint _strikePrice,
        bool _refundsEnabled,
        uint[3] memory _times, // [biddingEnd, maturity, expiry]
        uint[2] memory _bids, // [longBid, shortBid]
        uint[3] memory _fees // [poolFee, creatorFee, refundFee]
    ) public Owned(_owner) MixinResolver(_resolver) {
        creator = _creator;
        creatorLimits = BinaryOptionMarketManager.CreatorLimits(_creatorLimits[0], _creatorLimits[1]);

        oracleDetails = OracleDetails(_oracleKey, _strikePrice, 0);
        times = Times(_times[0], _times[1], _times[2]);

        refundsEnabled = _refundsEnabled;

        (uint longBid, uint shortBid) = (_bids[0], _bids[1]);
        _checkCreatorLimits(longBid, shortBid);
        emit Bid(Side.Long, _creator, longBid);
        emit Bid(Side.Short, _creator, shortBid);

        // Note that the initial deposit of synths must be made by the manager, otherwise the contract's assumed
        // deposits will fall out of sync with its actual balance. Similarly the total system deposits must be updated in the manager.
        // A balance check isn't performed here since the manager doesn't know the address of the new contract until after it is created.
        uint initialDeposit = longBid.add(shortBid);
        deposited = initialDeposit;

        (uint poolFee, uint creatorFee) = (_fees[0], _fees[1]);
        fees = BinaryOptionMarketManager.Fees(poolFee, creatorFee, _fees[2]);
        _feeMultiplier = SafeDecimalMath.unit().sub(poolFee.add(creatorFee));

        // Compute the prices now that the fees and deposits have been set.
        _updatePrices(longBid, shortBid, initialDeposit);

        // Instantiate the options themselves
        options.long = new BinaryOption(_creator, longBid);
        options.short = new BinaryOption(_creator, shortBid);
    }

    /* ========== VIEWS ========== */

    function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
        addresses = new bytes32[](4);
        addresses[0] = CONTRACT_SYSTEMSTATUS;
        addresses[1] = CONTRACT_EXRATES;
        addresses[2] = CONTRACT_SYNTHSUSD;
        addresses[3] = CONTRACT_FEEPOOL;
    }

    /* ---------- External Contracts ---------- */

    function _systemStatus() internal view returns (ISystemStatus) {
        return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEMSTATUS));
    }

    function _exchangeRates() internal view returns (IExchangeRates) {
        return IExchangeRates(requireAndGetAddress(CONTRACT_EXRATES));
    }

    function _sUSD() internal view returns (IERC20) {
        return IERC20(requireAndGetAddress(CONTRACT_SYNTHSUSD));
    }

    function _feePool() internal view returns (IFeePool) {
        return IFeePool(requireAndGetAddress(CONTRACT_FEEPOOL));
    }

    function _manager() internal view returns (BinaryOptionMarketManager) {
        return BinaryOptionMarketManager(owner);
    }

    /* ---------- Phases ---------- */

    function _biddingEnded() internal view returns (bool) {
        return times.biddingEnd < now;
    }

    function _matured() internal view returns (bool) {
        return times.maturity < now;
    }

    function _expired() internal view returns (bool) {
        return resolved && (times.expiry < now || deposited == 0);
    }

    function phase() external view returns (Phase) {
        if (!_biddingEnded()) {
            return Phase.Bidding;
        }
        if (!_matured()) {
            return Phase.Trading;
        }
        if (!_expired()) {
            return Phase.Maturity;
        }
        return Phase.Expiry;
    }

    /* ---------- Market Resolution ---------- */

    function _oraclePriceAndTimestamp() internal view returns (uint price, uint updatedAt) {
        return _exchangeRates().rateAndUpdatedTime(oracleDetails.key);
    }

    function oraclePriceAndTimestamp() external view returns (uint price, uint updatedAt) {
        return _oraclePriceAndTimestamp();
    }

    function _isFreshPriceUpdateTime(uint timestamp) internal view returns (bool) {
        (uint maxOraclePriceAge, , ) = _manager().durations();
        return (times.maturity.sub(maxOraclePriceAge)) <= timestamp;
    }

    function canResolve() external view returns (bool) {
        (, uint updatedAt) = _oraclePriceAndTimestamp();
        return !resolved && _matured() && _isFreshPriceUpdateTime(updatedAt);
    }

    function _result() internal view returns (Side) {
        uint price;
        if (resolved) {
            price = oracleDetails.finalPrice;
        } else {
            (price, ) = _oraclePriceAndTimestamp();
        }

        return oracleDetails.strikePrice <= price ? Side.Long : Side.Short;
    }

    function result() external view returns (Side) {
        return _result();
    }

    /* ---------- Option Prices ---------- */

    function _computePrices(
        uint longBids,
        uint shortBids,
        uint _deposited
    ) internal view returns (uint long, uint short) {
        require(longBids != 0 && shortBids != 0, "Bids must be nonzero");
        uint optionsPerSide = _exercisableDeposits(_deposited);

        // The math library rounds up on an exact half-increment -- the price on one side may be an increment too high,
        // but this only implies a tiny extra quantity will go to fees.
        return (longBids.divideDecimalRound(optionsPerSide), shortBids.divideDecimalRound(optionsPerSide));
    }

    function senderPriceAndExercisableDeposits() external view returns (uint price, uint exercisable) {
        // When the market is not yet resolved, both sides might be able to exercise all the options.
        // On the other hand, if the market has resolved, then only the winning side may exercise.
        exercisable = 0;
        if (!resolved || address(_option(_result())) == msg.sender) {
            exercisable = _exercisableDeposits(deposited);
        }

        // Send the correct price for each side of the market.
        if (msg.sender == address(options.long)) {
            price = prices.long;
        } else if (msg.sender == address(options.short)) {
            price = prices.short;
        } else {
            revert("Sender is not an option");
        }
    }

    function pricesAfterBidOrRefund(
        Side side,
        uint value,
        bool refund
    ) external view returns (uint long, uint short) {
        (uint longTotalBids, uint shortTotalBids) = _totalBids();
        // prettier-ignore
        function(uint, uint) pure returns (uint) operation = refund ? SafeMath.sub : SafeMath.add;

        if (side == Side.Long) {
            longTotalBids = operation(longTotalBids, value);
        } else {
            shortTotalBids = operation(shortTotalBids, value);
        }

        if (refund) {
            value = value.multiplyDecimalRound(SafeDecimalMath.unit().sub(fees.refundFee));
        }
        return _computePrices(longTotalBids, shortTotalBids, operation(deposited, value));
    }

    // Returns zero if the result would be negative. See the docs for the formulae this implements.
    function bidOrRefundForPrice(
        Side bidSide,
        Side priceSide,
        uint price,
        bool refund
    ) external view returns (uint) {
        uint adjustedPrice = price.multiplyDecimalRound(_feeMultiplier);
        uint bids = _option(priceSide).totalBids();
        uint _deposited = deposited;
        uint unit = SafeDecimalMath.unit();
        uint refundFeeMultiplier = unit.sub(fees.refundFee);

        if (bidSide == priceSide) {
            uint depositedByPrice = _deposited.multiplyDecimalRound(adjustedPrice);

            // For refunds, the numerator is the negative of the bid case and,
            // in the denominator the adjusted price has an extra factor of (1 - the refundFee).
            if (refund) {
                (depositedByPrice, bids) = (bids, depositedByPrice);
                adjustedPrice = adjustedPrice.multiplyDecimalRound(refundFeeMultiplier);
            }

            // The adjusted price is guaranteed to be less than 1: all its factors are also less than 1.
            return _subToZero(depositedByPrice, bids).divideDecimalRound(unit.sub(adjustedPrice));
        } else {
            uint bidsPerPrice = bids.divideDecimalRound(adjustedPrice);

            // For refunds, the numerator is the negative of the bid case.
            if (refund) {
                (bidsPerPrice, _deposited) = (_deposited, bidsPerPrice);
            }

            uint value = _subToZero(bidsPerPrice, _deposited);
            return refund ? value.divideDecimalRound(refundFeeMultiplier) : value;
        }
    }

    /* ---------- Option Balances and Bids ---------- */

    function _bidsOf(address account) internal view returns (uint long, uint short) {
        return (options.long.bidOf(account), options.short.bidOf(account));
    }

    function bidsOf(address account) external view returns (uint long, uint short) {
        return _bidsOf(account);
    }

    function _totalBids() internal view returns (uint long, uint short) {
        return (options.long.totalBids(), options.short.totalBids());
    }

    function totalBids() external view returns (uint long, uint short) {
        return _totalBids();
    }

    function _claimableBalancesOf(address account) internal view returns (uint long, uint short) {
        return (options.long.claimableBalanceOf(account), options.short.claimableBalanceOf(account));
    }

    function claimableBalancesOf(address account) external view returns (uint long, uint short) {
        return _claimableBalancesOf(account);
    }

    function totalClaimableSupplies() external view returns (uint long, uint short) {
        return (options.long.totalClaimableSupply(), options.short.totalClaimableSupply());
    }

    function _balancesOf(address account) internal view returns (uint long, uint short) {
        return (options.long.balanceOf(account), options.short.balanceOf(account));
    }

    function balancesOf(address account) external view returns (uint long, uint short) {
        return _balancesOf(account);
    }

    function totalSupplies() external view returns (uint long, uint short) {
        return (options.long.totalSupply(), options.short.totalSupply());
    }

    function _exercisableDeposits(uint _deposited) internal view returns (uint) {
        // Fees are deducted at resolution, so remove them if we're still bidding or trading.
        return resolved ? _deposited : _deposited.multiplyDecimalRound(_feeMultiplier);
    }

    function exercisableDeposits() external view returns (uint) {
        return _exercisableDeposits(deposited);
    }

    /* ---------- Utilities ---------- */

    function _chooseSide(
        Side side,
        uint longValue,
        uint shortValue
    ) internal pure returns (uint) {
        if (side == Side.Long) {
            return longValue;
        }
        return shortValue;
    }

    function _option(Side side) internal view returns (BinaryOption) {
        if (side == Side.Long) {
            return options.long;
        }
        return options.short;
    }

    // Returns zero if the result would be negative.
    function _subToZero(uint a, uint b) internal pure returns (uint) {
        return a < b ? 0 : a.sub(b);
    }

    function _checkCreatorLimits(uint longBid, uint shortBid) internal view {
        uint totalBid = longBid.add(shortBid);
        require(creatorLimits.capitalRequirement <= totalBid, "Insufficient capital");
        uint skewLimit = creatorLimits.skewLimit;
        require(
            skewLimit <= longBid.divideDecimal(totalBid) && skewLimit <= shortBid.divideDecimal(totalBid),
            "Bids too skewed"
        );
    }

    function _incrementDeposited(uint value) internal returns (uint _deposited) {
        _deposited = deposited.add(value);
        deposited = _deposited;
        _manager().incrementTotalDeposited(value);
    }

    function _decrementDeposited(uint value) internal returns (uint _deposited) {
        _deposited = deposited.sub(value);
        deposited = _deposited;
        _manager().decrementTotalDeposited(value);
    }

    function _requireManagerNotPaused() internal view {
        require(!_manager().paused(), "This action cannot be performed while the contract is paused");
    }

    function requireActiveAndUnpaused() external view {
        _systemStatus().requireSystemActive();
        _requireManagerNotPaused();
    }

    /* ========== MUTATIVE FUNCTIONS ========== */

    /* ---------- Bidding and Refunding ---------- */

    function _updatePrices(
        uint longBids,
        uint shortBids,
        uint _deposited
    ) internal {
        (uint256 longPrice, uint256 shortPrice) = _computePrices(longBids, shortBids, _deposited);
        prices = Prices(longPrice, shortPrice);
        emit PricesUpdated(longPrice, shortPrice);
    }

    function bid(Side side, uint value) external duringBidding {
        if (value == 0) {
            return;
        }

        _option(side).bid(msg.sender, value);
        emit Bid(side, msg.sender, value);

        uint _deposited = _incrementDeposited(value);
        _sUSD().transferFrom(msg.sender, address(this), value);

        (uint longTotalBids, uint shortTotalBids) = _totalBids();
        _updatePrices(longTotalBids, shortTotalBids, _deposited);
    }

    function refund(Side side, uint value) external duringBidding returns (uint refundMinusFee) {
        require(refundsEnabled, "Refunds disabled");
        if (value == 0) {
            return 0;
        }

        // Require the market creator to leave sufficient capital in the market.
        if (msg.sender == creator) {
            (uint thisBid, uint thatBid) = _bidsOf(msg.sender);
            if (side == Side.Short) {
                (thisBid, thatBid) = (thatBid, thisBid);
            }
            _checkCreatorLimits(thisBid.sub(value), thatBid);
        }

        // Safe subtraction here and in related contracts will fail if either the
        // total supply, deposits, or wallet balance are too small to support the refund.
        refundMinusFee = value.multiplyDecimalRound(SafeDecimalMath.unit().sub(fees.refundFee));

        _option(side).refund(msg.sender, value);
        emit Refund(side, msg.sender, refundMinusFee, value.sub(refundMinusFee));

        uint _deposited = _decrementDeposited(refundMinusFee);
        _sUSD().transfer(msg.sender, refundMinusFee);

        (uint longTotalBids, uint shortTotalBids) = _totalBids();
        _updatePrices(longTotalBids, shortTotalBids, _deposited);
    }

    /* ---------- Market Resolution ---------- */

    function resolve() external onlyOwner afterMaturity systemActive managerNotPaused {
        require(!resolved, "Market already resolved");

        // We don't need to perform stale price checks, so long as the price was
        // last updated recently enough before the maturity date.
        (uint price, uint updatedAt) = _oraclePriceAndTimestamp();
        require(_isFreshPriceUpdateTime(updatedAt), "Price is stale");

        oracleDetails.finalPrice = price;
        resolved = true;

        // Now remit any collected fees.
        // Since the constructor enforces that creatorFee + poolFee < 1, the balance
        // in the contract will be sufficient to cover these transfers.
        IERC20 sUSD = _sUSD();

        uint _deposited = deposited;
        uint poolFees = _deposited.multiplyDecimalRound(fees.poolFee);
        uint creatorFees = _deposited.multiplyDecimalRound(fees.creatorFee);
        _decrementDeposited(creatorFees.add(poolFees));
        sUSD.transfer(_feePool().FEE_ADDRESS(), poolFees);
        sUSD.transfer(creator, creatorFees);

        emit MarketResolved(_result(), price, updatedAt, deposited, poolFees, creatorFees);
    }

    /* ---------- Claiming and Exercising Options ---------- */

    function _claimOptions()
        internal
        systemActive
        managerNotPaused
        afterBidding
        returns (uint longClaimed, uint shortClaimed)
    {
        uint exercisable = _exercisableDeposits(deposited);
        Side outcome = _result();
        bool _resolved = resolved;

        // Only claim options if we aren't resolved, and only claim the winning side.
        uint longOptions;
        uint shortOptions;
        if (!_resolved || outcome == Side.Long) {
            longOptions = options.long.claim(msg.sender, prices.long, exercisable);
        }
        if (!_resolved || outcome == Side.Short) {
            shortOptions = options.short.claim(msg.sender, prices.short, exercisable);
        }

        require(longOptions != 0 || shortOptions != 0, "Nothing to claim");
        emit OptionsClaimed(msg.sender, longOptions, shortOptions);
        return (longOptions, shortOptions);
    }

    function claimOptions() external returns (uint longClaimed, uint shortClaimed) {
        return _claimOptions();
    }

    function exerciseOptions() external returns (uint) {
        // The market must be resolved if it has not been.
        if (!resolved) {
            _manager().resolveMarket(address(this));
        }

        // If there are options to be claimed, claim them and proceed.
        (uint claimableLong, uint claimableShort) = _claimableBalancesOf(msg.sender);
        if (claimableLong != 0 || claimableShort != 0) {
            _claimOptions();
        }

        // If the account holds no options, revert.
        (uint longBalance, uint shortBalance) = _balancesOf(msg.sender);
        require(longBalance != 0 || shortBalance != 0, "Nothing to exercise");

        // Each option only needs to be exercised if the account holds any of it.
        if (longBalance != 0) {
            options.long.exercise(msg.sender);
        }
        if (shortBalance != 0) {
            options.short.exercise(msg.sender);
        }

        // Only pay out the side that won.
        uint payout = _chooseSide(_result(), longBalance, shortBalance);
        emit OptionsExercised(msg.sender, payout);
        if (payout != 0) {
            _decrementDeposited(payout);
            _sUSD().transfer(msg.sender, payout);
        }
        return payout;
    }

    /* ---------- Market Expiry ---------- */

    function _selfDestruct(address payable beneficiary) internal {
        uint _deposited = deposited;
        if (_deposited != 0) {
            _decrementDeposited(_deposited);
        }

        // Transfer the balance rather than the deposit value in case there are any synths left over
        // from direct transfers.
        IERC20 sUSD = _sUSD();
        uint balance = sUSD.balanceOf(address(this));
        if (balance != 0) {
            sUSD.transfer(beneficiary, balance);
        }

        // Destroy the option tokens before destroying the market itself.
        options.long.expire(beneficiary);
        options.short.expire(beneficiary);
        selfdestruct(beneficiary);
    }

    function cancel(address payable beneficiary) external onlyOwner duringBidding {
        (uint longTotalBids, uint shortTotalBids) = _totalBids();
        (uint creatorLongBids, uint creatorShortBids) = _bidsOf(creator);
        bool cancellable = longTotalBids == creatorLongBids && shortTotalBids == creatorShortBids;
        require(cancellable, "Not cancellable");
        _selfDestruct(beneficiary);
    }

    function expire(address payable beneficiary) external onlyOwner {
        require(_expired(), "Unexpired options remaining");
        _selfDestruct(beneficiary);
    }

    /* ========== MODIFIERS ========== */

    modifier duringBidding() {
        require(!_biddingEnded(), "Bidding inactive");
        _;
    }

    modifier afterBidding() {
        require(_biddingEnded(), "Bidding incomplete");
        _;
    }

    modifier afterMaturity() {
        require(_matured(), "Not yet mature");
        _;
    }

    modifier systemActive() {
        _systemStatus().requireSystemActive();
        _;
    }

    modifier managerNotPaused() {
        _requireManagerNotPaused();
        _;
    }

    /* ========== EVENTS ========== */

    event Bid(Side side, address indexed account, uint value);
    event Refund(Side side, address indexed account, uint value, uint fee);
    event PricesUpdated(uint longPrice, uint shortPrice);
    event MarketResolved(
        Side result,
        uint oraclePrice,
        uint oracleTimestamp,
        uint deposited,
        uint poolFees,
        uint creatorFees
    );
    event OptionsClaimed(address indexed account, uint longOptions, uint shortOptions);
    event OptionsExercised(address indexed account, uint value);
}


// Inheritance


// Internal references


// https://docs.synthetix.io/contracts/source/contracts/binaryoptionmarketfactory
contract BinaryOptionMarketFactory is Owned, MixinResolver {
    /* ========== STATE VARIABLES ========== */

    /* ---------- Address Resolver Configuration ---------- */

    bytes32 internal constant CONTRACT_BINARYOPTIONMARKETMANAGER = "BinaryOptionMarketManager";

    /* ========== CONSTRUCTOR ========== */

    constructor(address _owner, address _resolver) public Owned(_owner) MixinResolver(_resolver) {}

    /* ========== VIEWS ========== */

    function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
        addresses = new bytes32[](1);
        addresses[0] = CONTRACT_BINARYOPTIONMARKETMANAGER;
    }

    /* ---------- Related Contracts ---------- */

    function _manager() internal view returns (address) {
        return requireAndGetAddress(CONTRACT_BINARYOPTIONMARKETMANAGER);
    }

    /* ========== MUTATIVE FUNCTIONS ========== */

    function createMarket(
        address creator,
        uint[2] calldata creatorLimits,
        bytes32 oracleKey,
        uint strikePrice,
        bool refundsEnabled,
        uint[3] calldata times, // [biddingEnd, maturity, expiry]
        uint[2] calldata bids, // [longBid, shortBid]
        uint[3] calldata fees // [poolFee, creatorFee, refundFee]
    ) external returns (BinaryOptionMarket) {
        address manager = _manager();
        require(address(manager) == msg.sender, "Only permitted by the manager.");

        return
            new BinaryOptionMarket(
                manager,
                creator,
                address(resolver),
                creatorLimits,
                oracleKey,
                strikePrice,
                refundsEnabled,
                times,
                bids,
                fees
            );
    }
}


// https://docs.synthetix.io/contracts/source/interfaces/isystemstatus
interface ISystemStatus {
    struct Status {
        bool canSuspend;
        bool canResume;
    }

    struct Suspension {
        bool suspended;
        // reason is an integer code,
        // 0 => no reason, 1 => upgrading, 2+ => defined by system usage
        uint248 reason;
    }

    // Views
    function accessControl(bytes32 section, address account) external view returns (bool canSuspend, bool canResume);

    function requireSystemActive() external view;

    function requireIssuanceActive() external view;

    function requireExchangeActive() external view;

    function requireSynthActive(bytes32 currencyKey) external view;

    function requireSynthsActive(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view;

    function synthSuspension(bytes32 currencyKey) external view returns (bool suspended, uint248 reason);

    // Restricted functions
    function suspendSynth(bytes32 currencyKey, uint256 reason) external;

    function updateAccessControl(
        bytes32 section,
        address account,
        bool canSuspend,
        bool canResume
    ) external;
}


// Inheritance


// Libraries


// Internal references


// https://docs.synthetix.io/contracts/source/contracts/binaryoptionmarketmanager
contract BinaryOptionMarketManager is Owned, Pausable, MixinResolver, IBinaryOptionMarketManager {
    /* ========== LIBRARIES ========== */

    using SafeMath for uint;
    using AddressSetLib for AddressSetLib.AddressSet;

    /* ========== TYPES ========== */

    struct Fees {
        uint poolFee;
        uint creatorFee;
        uint refundFee;
    }

    struct Durations {
        uint maxOraclePriceAge;
        uint expiryDuration;
        uint maxTimeToMaturity;
    }

    struct CreatorLimits {
        uint capitalRequirement;
        uint skewLimit;
    }

    /* ========== STATE VARIABLES ========== */

    Fees public fees;
    Durations public durations;
    CreatorLimits public creatorLimits;

    bool public marketCreationEnabled = true;
    uint public totalDeposited;

    AddressSetLib.AddressSet internal _activeMarkets;
    AddressSetLib.AddressSet internal _maturedMarkets;

    BinaryOptionMarketManager internal _migratingManager;

    /* ---------- Address Resolver Configuration ---------- */

    bytes32 internal constant CONTRACT_SYSTEMSTATUS = "SystemStatus";
    bytes32 internal constant CONTRACT_SYNTHSUSD = "SynthsUSD";
    bytes32 internal constant CONTRACT_EXRATES = "ExchangeRates";
    bytes32 internal constant CONTRACT_BINARYOPTIONMARKETFACTORY = "BinaryOptionMarketFactory";

    /* ========== CONSTRUCTOR ========== */

    constructor(
        address _owner,
        address _resolver,
        uint _maxOraclePriceAge,
        uint _expiryDuration,
        uint _maxTimeToMaturity,
        uint _creatorCapitalRequirement,
        uint _creatorSkewLimit,
        uint _poolFee,
        uint _creatorFee,
        uint _refundFee
    ) public Owned(_owner) Pausable() MixinResolver(_resolver) {
        // Temporarily change the owner so that the setters don't revert.
        owner = msg.sender;
        setExpiryDuration(_expiryDuration);
        setMaxOraclePriceAge(_maxOraclePriceAge);
        setMaxTimeToMaturity(_maxTimeToMaturity);
        setCreatorCapitalRequirement(_creatorCapitalRequirement);
        setCreatorSkewLimit(_creatorSkewLimit);
        setPoolFee(_poolFee);
        setCreatorFee(_creatorFee);
        setRefundFee(_refundFee);
        owner = _owner;
    }

    /* ========== VIEWS ========== */

    function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
        addresses = new bytes32[](4);
        addresses[0] = CONTRACT_SYSTEMSTATUS;
        addresses[1] = CONTRACT_SYNTHSUSD;
        addresses[2] = CONTRACT_EXRATES;
        addresses[3] = CONTRACT_BINARYOPTIONMARKETFACTORY;
    }

    /* ---------- Related Contracts ---------- */

    function _systemStatus() internal view returns (ISystemStatus) {
        return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEMSTATUS));
    }

    function _sUSD() internal view returns (IERC20) {
        return IERC20(requireAndGetAddress(CONTRACT_SYNTHSUSD));
    }

    function _exchangeRates() internal view returns (IExchangeRates) {
        return IExchangeRates(requireAndGetAddress(CONTRACT_EXRATES));
    }

    function _factory() internal view returns (BinaryOptionMarketFactory) {
        return BinaryOptionMarketFactory(requireAndGetAddress(CONTRACT_BINARYOPTIONMARKETFACTORY));
    }

    /* ---------- Market Information ---------- */

    function _isKnownMarket(address candidate) internal view returns (bool) {
        return _activeMarkets.contains(candidate) || _maturedMarkets.contains(candidate);
    }

    function numActiveMarkets() external view returns (uint) {
        return _activeMarkets.elements.length;
    }

    function activeMarkets(uint index, uint pageSize) external view returns (address[] memory) {
        return _activeMarkets.getPage(index, pageSize);
    }

    function numMaturedMarkets() external view returns (uint) {
        return _maturedMarkets.elements.length;
    }

    function maturedMarkets(uint index, uint pageSize) external view returns (address[] memory) {
        return _maturedMarkets.getPage(index, pageSize);
    }

    function _isValidKey(bytes32 oracleKey) internal view returns (bool) {
        IExchangeRates exchangeRates = _exchangeRates();

        // If it has a rate, then it's possibly a valid key
        if (exchangeRates.rateForCurrency(oracleKey) != 0) {
            // But not sUSD
            if (oracleKey == "sUSD") {
                return false;
            }

            // and not inverse rates
            (uint entryPoint, , , , ) = exchangeRates.inversePricing(oracleKey);
            if (entryPoint != 0) {
                return false;
            }

            return true;
        }

        return false;
    }

    /* ========== MUTATIVE FUNCTIONS ========== */

    /* ---------- Setters ---------- */

    function setMaxOraclePriceAge(uint _maxOraclePriceAge) public onlyOwner {
        durations.maxOraclePriceAge = _maxOraclePriceAge;
        emit MaxOraclePriceAgeUpdated(_maxOraclePriceAge);
    }

    function setExpiryDuration(uint _expiryDuration) public onlyOwner {
        durations.expiryDuration = _expiryDuration;
        emit ExpiryDurationUpdated(_expiryDuration);
    }

    function setMaxTimeToMaturity(uint _maxTimeToMaturity) public onlyOwner {
        durations.maxTimeToMaturity = _maxTimeToMaturity;
        emit MaxTimeToMaturityUpdated(_maxTimeToMaturity);
    }

    function setPoolFee(uint _poolFee) public onlyOwner {
        uint totalFee = _poolFee + fees.creatorFee;
        require(totalFee < SafeDecimalMath.unit(), "Total fee must be less than 100%.");
        require(0 < totalFee, "Total fee must be nonzero.");
        fees.poolFee = _poolFee;
        emit PoolFeeUpdated(_poolFee);
    }

    function setCreatorFee(uint _creatorFee) public onlyOwner {
        uint totalFee = _creatorFee + fees.poolFee;
        require(totalFee < SafeDecimalMath.unit(), "Total fee must be less than 100%.");
        require(0 < totalFee, "Total fee must be nonzero.");
        fees.creatorFee = _creatorFee;
        emit CreatorFeeUpdated(_creatorFee);
    }

    function setRefundFee(uint _refundFee) public onlyOwner {
        require(_refundFee <= SafeDecimalMath.unit(), "Refund fee must be no greater than 100%.");
        fees.refundFee = _refundFee;
        emit RefundFeeUpdated(_refundFee);
    }

    function setCreatorCapitalRequirement(uint _creatorCapitalRequirement) public onlyOwner {
        creatorLimits.capitalRequirement = _creatorCapitalRequirement;
        emit CreatorCapitalRequirementUpdated(_creatorCapitalRequirement);
    }

    function setCreatorSkewLimit(uint _creatorSkewLimit) public onlyOwner {
        require(_creatorSkewLimit <= SafeDecimalMath.unit(), "Creator skew limit must be no greater than 1.");
        creatorLimits.skewLimit = _creatorSkewLimit;
        emit CreatorSkewLimitUpdated(_creatorSkewLimit);
    }

    /* ---------- Deposit Management ---------- */

    function incrementTotalDeposited(uint delta) external onlyActiveMarkets notPaused {
        _systemStatus().requireSystemActive();
        totalDeposited = totalDeposited.add(delta);
    }

    function decrementTotalDeposited(uint delta) external onlyKnownMarkets notPaused {
        _systemStatus().requireSystemActive();
        // NOTE: As individual market debt is not tracked here, the underlying markets
        //       need to be careful never to subtract more debt than they added.
        //       This can't be enforced without additional state/communication overhead.
        totalDeposited = totalDeposited.sub(delta);
    }

    /* ---------- Market Lifecycle ---------- */

    function createMarket(
        bytes32 oracleKey,
        uint strikePrice,
        bool refundsEnabled,
        uint[2] calldata times, // [biddingEnd, maturity]
        uint[2] calldata bids // [longBid, shortBid]
    )
        external
        notPaused
        returns (
            IBinaryOptionMarket // no support for returning BinaryOptionMarket polymorphically given the interface
        )
    {
        _systemStatus().requireSystemActive();
        require(marketCreationEnabled, "Market creation is disabled");
        require(_isValidKey(oracleKey), "Invalid key");

        (uint biddingEnd, uint maturity) = (times[0], times[1]);
        require(maturity <= now + durations.maxTimeToMaturity, "Maturity too far in the future");
        uint expiry = maturity.add(durations.expiryDuration);

        uint initialDeposit = bids[0].add(bids[1]);
        require(now < biddingEnd, "End of bidding has passed");
        require(biddingEnd < maturity, "Maturity predates end of bidding");
        // We also require maturity < expiry. But there is no need to check this.
        // Fees being in range are checked in the setters.
        // The market itself validates the capital and skew requirements.

        BinaryOptionMarket market = _factory().createMarket(
            msg.sender,
            [creatorLimits.capitalRequirement, creatorLimits.skewLimit],
            oracleKey,
            strikePrice,
            refundsEnabled,
            [biddingEnd, maturity, expiry],
            bids,
            [fees.poolFee, fees.creatorFee, fees.refundFee]
        );
        market.rebuildCache();
        _activeMarkets.add(address(market));

        // The debt can't be incremented in the new market's constructor because until construction is complete,
        // the manager doesn't know its address in order to grant it permission.
        totalDeposited = totalDeposited.add(initialDeposit);
        _sUSD().transferFrom(msg.sender, address(market), initialDeposit);

        emit MarketCreated(address(market), msg.sender, oracleKey, strikePrice, biddingEnd, maturity, expiry);
        return market;
    }

    function resolveMarket(address market) external {
        require(_activeMarkets.contains(market), "Not an active market");
        BinaryOptionMarket(market).resolve();
        _activeMarkets.remove(market);
        _maturedMarkets.add(market);
    }

    function cancelMarket(address market) external notPaused {
        require(_activeMarkets.contains(market), "Not an active market");
        address creator = BinaryOptionMarket(market).creator();
        require(msg.sender == creator, "Sender not market creator");
        BinaryOptionMarket(market).cancel(msg.sender);
        _activeMarkets.remove(market);
        emit MarketCancelled(market);
    }

    function expireMarkets(address[] calldata markets) external notPaused {
        for (uint i = 0; i < markets.length; i++) {
            address market = markets[i];

            // The market itself handles decrementing the total deposits.
            BinaryOptionMarket(market).expire(msg.sender);
            // Note that we required that the market is known, which guarantees
            // its index is defined and that the list of markets is not empty.
            _maturedMarkets.remove(market);
            emit MarketExpired(market);
        }
    }

    /* ---------- Upgrade and Administration ---------- */

    function rebuildMarketCaches(BinaryOptionMarket[] calldata marketsToSync) external {
        for (uint i = 0; i < marketsToSync.length; i++) {
            address market = address(marketsToSync[i]);

            // solhint-disable avoid-low-level-calls
            bytes memory payload = abi.encodeWithSignature("rebuildCache()");
            (bool success, ) = market.call(payload);

            if (!success) {
                // handle legacy markets that used an old cache rebuilding logic
                bytes memory payloadForLegacyCache = abi.encodeWithSignature(
                    "setResolverAndSyncCache(address)",
                    address(resolver)
                );

                // solhint-disable avoid-low-level-calls
                (bool legacySuccess, ) = market.call(payloadForLegacyCache);
                require(legacySuccess, "Cannot rebuild cache for market");
            }
        }
    }

    function setMarketCreationEnabled(bool enabled) public onlyOwner {
        if (enabled != marketCreationEnabled) {
            marketCreationEnabled = enabled;
            emit MarketCreationEnabledUpdated(enabled);
        }
    }

    function setMigratingManager(BinaryOptionMarketManager manager) public onlyOwner {
        _migratingManager = manager;
    }

    function migrateMarkets(
        BinaryOptionMarketManager receivingManager,
        bool active,
        BinaryOptionMarket[] calldata marketsToMigrate
    ) external onlyOwner {
        uint _numMarkets = marketsToMigrate.length;
        if (_numMarkets == 0) {
            return;
        }
        AddressSetLib.AddressSet storage markets = active ? _activeMarkets : _maturedMarkets;

        uint runningDepositTotal;
        for (uint i; i < _numMarkets; i++) {
            BinaryOptionMarket market = marketsToMigrate[i];
            require(_isKnownMarket(address(market)), "Market unknown.");

            // Remove it from our list and deposit total.
            markets.remove(address(market));
            runningDepositTotal = runningDepositTotal.add(market.deposited());

            // Prepare to transfer ownership to the new manager.
            market.nominateNewOwner(address(receivingManager));
        }
        // Deduct the total deposits of the migrated markets.
        totalDeposited = totalDeposited.sub(runningDepositTotal);
        emit MarketsMigrated(receivingManager, marketsToMigrate);

        // Now actually transfer the markets over to the new manager.
        receivingManager.receiveMarkets(active, marketsToMigrate);
    }

    function receiveMarkets(bool active, BinaryOptionMarket[] calldata marketsToReceive) external {
        require(msg.sender == address(_migratingManager), "Only permitted for migrating manager.");

        uint _numMarkets = marketsToReceive.length;
        if (_numMarkets == 0) {
            return;
        }
        AddressSetLib.AddressSet storage markets = active ? _activeMarkets : _maturedMarkets;

        uint runningDepositTotal;
        for (uint i; i < _numMarkets; i++) {
            BinaryOptionMarket market = marketsToReceive[i];
            require(!_isKnownMarket(address(market)), "Market already known.");

            market.acceptOwnership();
            markets.add(address(market));
            // Update the market with the new manager address,
            runningDepositTotal = runningDepositTotal.add(market.deposited());
        }
        totalDeposited = totalDeposited.add(runningDepositTotal);
        emit MarketsReceived(_migratingManager, marketsToReceive);
    }

    /* ========== MODIFIERS ========== */

    modifier onlyActiveMarkets() {
        require(_activeMarkets.contains(msg.sender), "Permitted only for active markets.");
        _;
    }

    modifier onlyKnownMarkets() {
        require(_isKnownMarket(msg.sender), "Permitted only for known markets.");
        _;
    }

    /* ========== EVENTS ========== */

    event MarketCreated(
        address market,
        address indexed creator,
        bytes32 indexed oracleKey,
        uint strikePrice,
        uint biddingEndDate,
        uint maturityDate,
        uint expiryDate
    );
    event MarketExpired(address market);
    event MarketCancelled(address market);
    event MarketsMigrated(BinaryOptionMarketManager receivingManager, BinaryOptionMarket[] markets);
    event MarketsReceived(BinaryOptionMarketManager migratingManager, BinaryOptionMarket[] markets);
    event MarketCreationEnabledUpdated(bool enabled);
    event MaxOraclePriceAgeUpdated(uint duration);
    event ExerciseDurationUpdated(uint duration);
    event ExpiryDurationUpdated(uint duration);
    event MaxTimeToMaturityUpdated(uint duration);
    event CreatorCapitalRequirementUpdated(uint value);
    event CreatorSkewLimitUpdated(uint value);
    event PoolFeeUpdated(uint fee);
    event CreatorFeeUpdated(uint fee);
    event RefundFeeUpdated(uint fee);
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_resolver","type":"address"},{"internalType":"uint256","name":"_maxOraclePriceAge","type":"uint256"},{"internalType":"uint256","name":"_expiryDuration","type":"uint256"},{"internalType":"uint256","name":"_maxTimeToMaturity","type":"uint256"},{"internalType":"uint256","name":"_creatorCapitalRequirement","type":"uint256"},{"internalType":"uint256","name":"_creatorSkewLimit","type":"uint256"},{"internalType":"uint256","name":"_poolFee","type":"uint256"},{"internalType":"uint256","name":"_creatorFee","type":"uint256"},{"internalType":"uint256","name":"_refundFee","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"name","type":"bytes32"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"CacheUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"CreatorCapitalRequirementUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"CreatorFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"CreatorSkewLimitUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"ExerciseDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"ExpiryDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"}],"name":"MarketCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":true,"internalType":"address","name":"creator","type":"address"},{"indexed":true,"internalType":"bytes32","name":"oracleKey","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"strikePrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"biddingEndDate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maturityDate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expiryDate","type":"uint256"}],"name":"MarketCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"MarketCreationEnabledUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"}],"name":"MarketExpired","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract BinaryOptionMarketManager","name":"receivingManager","type":"address"},{"indexed":false,"internalType":"contract BinaryOptionMarket[]","name":"markets","type":"address[]"}],"name":"MarketsMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract BinaryOptionMarketManager","name":"migratingManager","type":"address"},{"indexed":false,"internalType":"contract BinaryOptionMarket[]","name":"markets","type":"address[]"}],"name":"MarketsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"MaxOraclePriceAgeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"MaxTimeToMaturityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isPaused","type":"bool"}],"name":"PauseChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"PoolFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"RefundFeeUpdated","type":"event"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"pageSize","type":"uint256"}],"name":"activeMarkets","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"cancelMarket","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"oracleKey","type":"bytes32"},{"internalType":"uint256","name":"strikePrice","type":"uint256"},{"internalType":"bool","name":"refundsEnabled","type":"bool"},{"internalType":"uint256[2]","name":"times","type":"uint256[2]"},{"internalType":"uint256[2]","name":"bids","type":"uint256[2]"}],"name":"createMarket","outputs":[{"internalType":"contract IBinaryOptionMarket","name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"creatorLimits","outputs":[{"internalType":"uint256","name":"capitalRequirement","type":"uint256"},{"internalType":"uint256","name":"skewLimit","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"delta","type":"uint256"}],"name":"decrementTotalDeposited","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"durations","outputs":[{"internalType":"uint256","name":"maxOraclePriceAge","type":"uint256"},{"internalType":"uint256","name":"expiryDuration","type":"uint256"},{"internalType":"uint256","name":"maxTimeToMaturity","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address[]","name":"markets","type":"address[]"}],"name":"expireMarkets","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"fees","outputs":[{"internalType":"uint256","name":"poolFee","type":"uint256"},{"internalType":"uint256","name":"creatorFee","type":"uint256"},{"internalType":"uint256","name":"refundFee","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"delta","type":"uint256"}],"name":"incrementTotalDeposited","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isResolverCached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastPauseTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"marketCreationEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"pageSize","type":"uint256"}],"name":"maturedMarkets","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"contract BinaryOptionMarketManager","name":"receivingManager","type":"address"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"contract BinaryOptionMarket[]","name":"marketsToMigrate","type":"address[]"}],"name":"migrateMarkets","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"numActiveMarkets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"numMaturedMarkets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"rebuildCache","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract BinaryOptionMarket[]","name":"marketsToSync","type":"address[]"}],"name":"rebuildMarketCaches","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"contract BinaryOptionMarket[]","name":"marketsToReceive","type":"address[]"}],"name":"receiveMarkets","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"resolveMarket","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"resolver","outputs":[{"internalType":"contract AddressResolver","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"resolverAddressesRequired","outputs":[{"internalType":"bytes32[]","name":"addresses","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_creatorCapitalRequirement","type":"uint256"}],"name":"setCreatorCapitalRequirement","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_creatorFee","type":"uint256"}],"name":"setCreatorFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_creatorSkewLimit","type":"uint256"}],"name":"setCreatorSkewLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_expiryDuration","type":"uint256"}],"name":"setExpiryDuration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setMarketCreationEnabled","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_maxOraclePriceAge","type":"uint256"}],"name":"setMaxOraclePriceAge","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_maxTimeToMaturity","type":"uint256"}],"name":"setMaxTimeToMaturity","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract BinaryOptionMarketManager","name":"manager","type":"address"}],"name":"setMigratingManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_poolFee","type":"uint256"}],"name":"setPoolFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_refundFee","type":"uint256"}],"name":"setRefundFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalDeposited","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]

6080604052600d805460ff191660011790553480156200001e57600080fd5b50604051620038d9380380620038d983398181016040526101408110156200004557600080fd5b508051602082015160408301516060840151608085015160a086015160c087015160e08801516101008901516101209099015197989697959694959394929391929091888a6001600160a01b038116620000e6576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b038316908117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a1506000546001600160a01b031662000191576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055600080546001600160a01b03191633179055620001dd876001600160e01b036200029a16565b620001f1886001600160e01b03620002e816565b62000205866001600160e01b036200033616565b62000219856001600160e01b036200038416565b6200022d846001600160e01b03620003d216565b62000241836001600160e01b03620004d316565b62000255826001600160e01b036200063616565b62000269816001600160e01b036200079916565b5050600080546001600160a01b0319166001600160a01b03999099169890981790975550620008e795505050505050565b620002ad6001600160e01b036200089a16565b60098190556040805182815290517ff378a0fd4ad3ffd9d7d50986f16b04acd2dc42691c4f412f34e8eefe883e66529181900360200190a150565b620002fb6001600160e01b036200089a16565b60088190556040805182815290517f5a2f2eae84f9e787d8159d363a776fa2b61d084686190cdc5a2c1ea833480b099181900360200190a150565b620003496001600160e01b036200089a16565b600a8190556040805182815290517f6de18e808fc4e6cb9c8910cf4bdc188ddbbdab65faecff65dab871720e8484899181900360200190a150565b620003976001600160e01b036200089a16565b600b8190556040805182815290517fdf7a26ae2e2eb953b81fd76b72fcdc74ebff7c21faa8f8f55323183d9785f52d9181900360200190a150565b620003e56001600160e01b036200089a16565b731a60e2e2a8be0bc2b6381dd31fd3fd5f9a28de4c63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b1580156200042a57600080fd5b505af41580156200043f573d6000803e3d6000fd5b505050506040513d60208110156200045657600080fd5b5051811115620004985760405162461bcd60e51b815260040180806020018281038252602d81526020018062003834602d913960400191505060405180910390fd5b600c8190556040805182815290517fd39cfbe31b20dbb6d995a675cf5c369555bf8bb908b6efc03873907fe9e133cf9181900360200190a150565b620004e66001600160e01b036200089a16565b600060056001015482019050731a60e2e2a8be0bc2b6381dd31fd3fd5f9a28de4c63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b1580156200053757600080fd5b505af41580156200054c573d6000803e3d6000fd5b505050506040513d60208110156200056357600080fd5b50518110620005a45760405162461bcd60e51b8152600401808060200182810382526021815260200180620038616021913960400191505060405180910390fd5b80600010620005fa576040805162461bcd60e51b815260206004820152601a60248201527f546f74616c20666565206d757374206265206e6f6e7a65726f2e000000000000604482015290519081900360640190fd5b60058290556040805183815290517f7b30e8f8e3de254785fbcb3068449dc18060f1fdb37b02731ecada99a78492c39181900360200190a15050565b620006496001600160e01b036200089a16565b600060056000015482019050731a60e2e2a8be0bc2b6381dd31fd3fd5f9a28de4c63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b1580156200069a57600080fd5b505af4158015620006af573d6000803e3d6000fd5b505050506040513d6020811015620006c657600080fd5b50518110620007075760405162461bcd60e51b8152600401808060200182810382526021815260200180620038616021913960400191505060405180910390fd5b806000106200075d576040805162461bcd60e51b815260206004820152601a60248201527f546f74616c20666565206d757374206265206e6f6e7a65726f2e000000000000604482015290519081900360640190fd5b60068290556040805183815290517f8c14462add32e0ae0fbfcf9e60711ecae573da337dc9127fff98fb7cfb3973b49181900360200190a15050565b620007ac6001600160e01b036200089a16565b731a60e2e2a8be0bc2b6381dd31fd3fd5f9a28de4c63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015620007f157600080fd5b505af415801562000806573d6000803e3d6000fd5b505050506040513d60208110156200081d57600080fd5b50518111156200085f5760405162461bcd60e51b8152600401808060200182810382526028815260200180620038b16028913960400191505060405180910390fd5b60078190556040805182815290517f01634ac4e9f09be1ef87b8d09e14926870261dcb9a0929d2d6460af6e4c5ad1e9181900360200190a150565b6000546001600160a01b03163314620008e55760405162461bcd60e51b815260040180806020018281038252602f81526020018062003882602f913960400191505060405180910390fd5b565b612f3d80620008f76000396000f3fe608060405234801561001057600080fd5b506004361061023d5760003560e01c80637859f4101161013b578063ac60c486116100b8578063c014fb841161007c578063c014fb84146106fc578063c095daf21461076a578063e73efc9b14610787578063fe40c470146107aa578063ff50abdc146107d05761023d565b8063ac60c48614610622578063adfd31af1461062a578063aeab5849146106a1578063bd6a10b8146106be578063be5af9fe146106db5761023d565b806391b4ded9116100ff57806391b4ded91461055257806394fcf3c31461055a5780639501dc871461058f5780639af1d35a146105ac5780639b11dc40146105b45761023d565b80637859f410146104a157806379ba5097146104c7578063899ffef4146104cf57806389c6318d146105275780638da5cb5b1461054a5761023d565b806336fd711e116101c957806364af2d871161018d57806364af2d871461043a57806364cf34bd146104425780636b3a09841461045f57806373b7de151461047c57806374185360146104995761023d565b806336fd711e146103c857806339ab4c41146103e55780634a41d89d1461040457806353a47bb71461042a5780635c975abb146104325761023d565b8063155028401161021057806315502840146103245780631627540c1461034157806316c38b3c146103675780631f3f10b0146103865780632af64bd3146103ac5761023d565b806302610c501461024257806303ff60181461025c57806304f3bcec146102e35780630dd16fd514610307575b600080fd5b61024a6107d8565b60408051918252519081900360200190f35b6102e16004803603606081101561027257600080fd5b6001600160a01b03823516916020810135151591810190606081016040820135600160201b8111156102a357600080fd5b8201836020820111156102b557600080fd5b803590602001918460208302840111600160201b831117156102d657600080fd5b5090925090506107df565b005b6102eb610ab1565b604080516001600160a01b039092168252519081900360200190f35b6102e16004803603602081101561031d57600080fd5b5035610ac5565b6102e16004803603602081101561033a57600080fd5b5035610c17565b6102e16004803603602081101561035757600080fd5b50356001600160a01b0316610c5a565b6102e16004803603602081101561037d57600080fd5b50351515610cb6565b6102e16004803603602081101561039c57600080fd5b50356001600160a01b0316610d30565b6103b4610d5a565b604080519115158252519081900360200190f35b6102e1600480360360208110156103de57600080fd5b5035610e6a565b6102e1600480360360208110156103fb57600080fd5b50351515610f5b565b61040c610fba565b60408051938452602084019290925282820152519081900360600190f35b6102eb610fc6565b6103b4610fd5565b6103b4610fde565b6102e16004803603602081101561045857600080fd5b5035610fe7565b6102e16004803603602081101561047557600080fd5b503561102a565b6102e16004803603602081101561049257600080fd5b5035611122565b6102e1611213565b6102e1600480360360208110156104b757600080fd5b50356001600160a01b03166113f0565b6102e16114c1565b6104d761157d565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105135781810151838201526020016104fb565b505050509050019250505060405180910390f35b6104d76004803603604081101561053d57600080fd5b5080359060200135611652565b6102eb61166f565b61024a61167e565b6102eb600480360360e081101561057057600080fd5b508035906020810135906040810135151590606081019060a001611684565b6102e1600480360360208110156105a557600080fd5b5035611c2a565b61040c611d7c565b6102e1600480360360208110156105ca57600080fd5b810190602081018135600160201b8111156105e457600080fd5b8201836020820111156105f657600080fd5b803590602001918460208302840111600160201b8311171561061757600080fd5b509092509050611d88565b61024a611fd0565b6102e16004803603604081101561064057600080fd5b813515159190810190604081016020820135600160201b81111561066357600080fd5b82018360208201111561067557600080fd5b803590602001918460208302840111600160201b8311171561069657600080fd5b509092509050611fd6565b6102e1600480360360208110156106b757600080fd5b5035612206565b6102e1600480360360208110156106d457600080fd5b5035612300565b6106e3612343565b6040805192835260208301919091528051918290030190f35b6102e16004803603602081101561071257600080fd5b810190602081018135600160201b81111561072c57600080fd5b82018360208201111561073e57600080fd5b803590602001918460208302840111600160201b8311171561075f57600080fd5b50909250905061234c565b6102e16004803603602081101561078057600080fd5b5035612482565b6104d76004803603604081101561079d57600080fd5b50803590602001356124c5565b6102e1600480360360208110156107c057600080fd5b50356001600160a01b03166124d9565b61024a6126ed565b600f545b90565b6107e76126f3565b80806107f35750610aab565b600084610801576011610804565b600f5b90506000805b8381101561098257600086868381811061082057fe5b905060200201356001600160a01b0316905061083b8161273e565b61087e576040805162461bcd60e51b815260206004820152600f60248201526e26b0b935b2ba103ab735b737bbb71760891b604482015290519081900360640190fd5b61088e848263ffffffff61277016565b610903816001600160a01b031663eef49ee36040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ca57600080fd5b505afa1580156108de573d6000803e3d6000fd5b505050506040513d60208110156108f457600080fd5b5051849063ffffffff6128b116565b9250806001600160a01b0316631627540c8a6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050600060405180830381600087803b15801561095d57600080fd5b505af1158015610971573d6000803e3d6000fd5b50506001909301925061080a915050565b50600e54610996908263ffffffff61290b16565b600e55604080516001600160a01b038916815260208082018381529282018790527f3e429aa34462b428d3f7277acb67e1c83d80a57faab2a47924369b5060f35679928a92899289929060608301908590850280828437600083820152604051601f909101601f1916909201829003965090945050505050a16040805163adfd31af60e01b81528715156004820190815260248201928352604482018790526001600160a01b038a169263adfd31af928a928a928a92606401846020850280828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b158015610a8f57600080fd5b505af1158015610aa3573d6000803e3d6000fd5b505050505050505b50505050565b60035461010090046001600160a01b031681565b610acd6126f3565b600060056000015482019050731a60e2e2a8be0bc2b6381dd31fd3fd5f9a28de4c63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015610b1d57600080fd5b505af4158015610b31573d6000803e3d6000fd5b505050506040513d6020811015610b4757600080fd5b50518110610b865760405162461bcd60e51b8152600401808060200182810382526021815260200180612ded6021913960400191505060405180910390fd5b80600010610bdb576040805162461bcd60e51b815260206004820152601a60248201527f546f74616c20666565206d757374206265206e6f6e7a65726f2e000000000000604482015290519081900360640190fd5b60068290556040805183815290517f8c14462add32e0ae0fbfcf9e60711ecae573da337dc9127fff98fb7cfb3973b49181900360200190a15050565b610c1f6126f3565b60098190556040805182815290517ff378a0fd4ad3ffd9d7d50986f16b04acd2dc42691c4f412f34e8eefe883e66529181900360200190a150565b610c626126f3565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b610cbe6126f3565b60035460ff1615158115151415610cd457610d2d565b6003805460ff1916821515179081905560ff1615610cf157426002555b6003546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b610d386126f3565b601380546001600160a01b0319166001600160a01b0392909216919091179055565b60006060610d6661157d565b905060005b8151811015610e61576000828281518110610d8257fe5b602090810291909101810151600081815260048084526040918290205460035483516321f8a72160e01b815292830185905292519395506001600160a01b039081169461010090930416926321f8a72192602480840193919291829003018186803b158015610df057600080fd5b505afa158015610e04573d6000803e3d6000fd5b505050506040513d6020811015610e1a57600080fd5b50516001600160a01b0316141580610e4757506000818152600460205260409020546001600160a01b0316155b15610e5857600093505050506107dc565b50600101610d6b565b50600191505090565b610e726126f3565b731a60e2e2a8be0bc2b6381dd31fd3fd5f9a28de4c63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015610eb657600080fd5b505af4158015610eca573d6000803e3d6000fd5b505050506040513d6020811015610ee057600080fd5b5051811115610f205760405162461bcd60e51b8152600401808060200182810382526028815260200180612ee16028913960400191505060405180910390fd5b60078190556040805182815290517f01634ac4e9f09be1ef87b8d09e14926870261dcb9a0929d2d6460af6e4c5ad1e9181900360200190a150565b610f636126f3565b600d5460ff16151581151514610d2d57600d805482151560ff19909116811790915560408051918252517fcc590b6309435383b617aaa0cae6aba938f2ee471cfb539201dd7655a23caff99181900360200190a150565b600854600954600a5483565b6001546001600160a01b031681565b60035460ff1681565b600d5460ff1681565b610fef6126f3565b600a8190556040805182815290517f6de18e808fc4e6cb9c8910cf4bdc188ddbbdab65faecff65dab871720e8484899181900360200190a150565b6110333361273e565b61106e5760405162461bcd60e51b8152600401808060200182810382526021815260200180612e306021913960400191505060405180910390fd5b60035460ff16156110b05760405162461bcd60e51b815260040180806020018281038252603c815260200180612ea5603c913960400191505060405180910390fd5b6110b8612968565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b1580156110f057600080fd5b505afa158015611104573d6000803e3d6000fd5b5050600e5461111c925090508263ffffffff61290b16565b600e5550565b61112a6126f3565b731a60e2e2a8be0bc2b6381dd31fd3fd5f9a28de4c63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b15801561116e57600080fd5b505af4158015611182573d6000803e3d6000fd5b505050506040513d602081101561119857600080fd5b50518111156111d85760405162461bcd60e51b815260040180806020018281038252602d815260200180612dc0602d913960400191505060405180910390fd5b600c8190556040805182815290517fd39cfbe31b20dbb6d995a675cf5c369555bf8bb908b6efc03873907fe9e133cf9181900360200190a150565b606061121d61157d565b905060005b81518110156113ec57600082828151811061123957fe5b602002602001015190506000600360019054906101000a90046001600160a01b03166001600160a01b031663dacb2d01838460405160200180807f5265736f6c766572206d697373696e67207461726765743a20000000000000008152506019018281526020019150506040516020818303038152906040526040518363ffffffff1660e01b81526004018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156113045781810151838201526020016112ec565b50505050905090810190601f1680156113315780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b15801561134f57600080fd5b505afa158015611363573d6000803e3d6000fd5b505050506040513d602081101561137957600080fd5b505160008381526004602090815260409182902080546001600160a01b0319166001600160a01b03851690811790915582518681529182015281519293507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68929081900390910190a15050600101611222565b5050565b611401600f8263ffffffff61298716565b611449576040805162461bcd60e51b8152602060048201526014602482015273139bdd08185b881858dd1a5d99481b585c9ad95d60621b604482015290519081900360640190fd5b806001600160a01b0316632810e1d66040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561148457600080fd5b505af1158015611498573d6000803e3d6000fd5b505050506114b081600f61277090919063ffffffff16565b610d2d60118263ffffffff6129f516565b6001546001600160a01b0316331461150a5760405162461bcd60e51b8152600401808060200182810382526035815260200180612d8b6035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60408051600480825260a08201909252606091602082016080803883390190505090506b53797374656d53746174757360a01b816000815181106115bd57fe5b6020026020010181815250506814de5b9d1a1cd554d160ba1b816001815181106115e357fe5b6020026020010181815250506c45786368616e6765526174657360981b8160028151811061160d57fe5b6020026020010181815250507842696e6172794f7074696f6e4d61726b6574466163746f727960381b8160038151811061164357fe5b60200260200101818152505090565b60606116666011848463ffffffff612a4716565b90505b92915050565b6000546001600160a01b031681565b60025481565b60035460009060ff16156116c95760405162461bcd60e51b815260040180806020018281038252603c815260200180612ea5603c913960400191505060405180910390fd5b6116d1612968565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b15801561170957600080fd5b505afa15801561171d573d6000803e3d6000fd5b5050600d5460ff16915061177a9050576040805162461bcd60e51b815260206004820152601b60248201527f4d61726b6574206372656174696f6e2069732064697361626c65640000000000604482015290519081900360640190fd5b61178386612b1d565b6117c2576040805162461bcd60e51b815260206004820152600b60248201526a496e76616c6964206b657960a81b604482015290519081900360640190fd5b600a548335906020850135904201811115611824576040805162461bcd60e51b815260206004820152601e60248201527f4d6174757269747920746f6f2066617220696e20746865206675747572650000604482015290519081900360640190fd5b60095460009061183b90839063ffffffff6128b116565b9050600061184e863560208801356128b1565b90508342106118a4576040805162461bcd60e51b815260206004820152601960248201527f456e64206f662062696464696e67206861732070617373656400000000000000604482015290519081900360640190fd5b8284106118f8576040805162461bcd60e51b815260206004820181905260248201527f4d6174757269747920707265646174657320656e64206f662062696464696e67604482015290519081900360640190fd5b6000611902612c51565b6001600160a01b031663130efa50336040518060400160405280600b600001548152602001600b600101548152508e8e8e60405180606001604052808d81526020018c81526020018b8152508e6040518060600160405280600560000154815260200160056001015481526020016005600201548152506040518963ffffffff1660e01b815260040180896001600160a01b03166001600160a01b0316815260200188600260200280838360005b838110156119c85781810151838201526020016119b0565b505050509050018781526020018681526020018515151515815260200184600360200280838360005b83811015611a095781810151838201526020016119f1565b5050505090500183600260200280828437600081840152601f19601f82011690508083019250505082600360200280838360005b83811015611a55578181015183820152602001611a3d565b5050505090500198505050505050505050602060405180830381600087803b158015611a8057600080fd5b505af1158015611a94573d6000803e3d6000fd5b505050506040513d6020811015611aaa57600080fd5b5051604080516303a0c29b60e51b815290519192506001600160a01b0383169163741853609160048082019260009290919082900301818387803b158015611af157600080fd5b505af1158015611b05573d6000803e3d6000fd5b50505050611b1d81600f6129f590919063ffffffff16565b600e54611b30908363ffffffff6128b116565b600e55611b3b612c78565b604080516323b872dd60e01b81523360048201526001600160a01b03848116602483015260448201869052915192909116916323b872dd916064808201926020929091908290030181600087803b158015611b9557600080fd5b505af1158015611ba9573d6000803e3d6000fd5b505050506040513d6020811015611bbf57600080fd5b5050604080516001600160a01b0383168152602081018c9052808201879052606081018690526080810185905290518c9133917fbcd154709bbe69680012cadcd07d57bd4a0ec64a033c2a3e31d2d0fadb38d3a89181900360a00190a39a9950505050505050505050565b611c326126f3565b600060056001015482019050731a60e2e2a8be0bc2b6381dd31fd3fd5f9a28de4c63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015611c8257600080fd5b505af4158015611c96573d6000803e3d6000fd5b505050506040513d6020811015611cac57600080fd5b50518110611ceb5760405162461bcd60e51b8152600401808060200182810382526021815260200180612ded6021913960400191505060405180910390fd5b80600010611d40576040805162461bcd60e51b815260206004820152601a60248201527f546f74616c20666565206d757374206265206e6f6e7a65726f2e000000000000604482015290519081900360640190fd5b60058290556040805183815290517f7b30e8f8e3de254785fbcb3068449dc18060f1fdb37b02731ecada99a78492c39181900360200190a15050565b60055460065460075483565b60005b81811015611fcb576000838383818110611da157fe5b6040805160048152602481018252602081810180516001600160e01b03166303a0c29b60e51b178152925182516001600160a01b0392909502969096013516955093600093508592859282918083835b60208310611e105780518252601f199092019160209182019101611df1565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611e72576040519150601f19603f3d011682016040523d82523d6000602084013e611e77565b606091505b5050905080611fc057600354604080516001600160a01b03610100909304831660248083019190915282518083039091018152604490910182526020810180516001600160e01b0316633be99e6f60e01b1781529151815191936000939088169285929182918083835b60208310611f005780518252601f199092019160209182019101611ee1565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611f62576040519150601f19603f3d011682016040523d82523d6000602084013e611f67565b606091505b5050905080611fbd576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742072656275696c6420636163686520666f72206d61726b657400604482015290519081900360640190fd5b50505b505050600101611d8b565b505050565b60115490565b6013546001600160a01b0316331461201f5760405162461bcd60e51b8152600401808060200182810382526025815260200180612e806025913960400191505060405180910390fd5b808061202b5750611fcb565b60008461203957601161203c565b600f5b90506000805b8381101561216a57600086868381811061205857fe5b905060200201356001600160a01b031690506120738161273e565b156120bd576040805162461bcd60e51b815260206004820152601560248201527426b0b935b2ba1030b63932b0b23c9035b737bbb71760591b604482015290519081900360640190fd5b806001600160a01b03166379ba50976040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156120f857600080fd5b505af115801561210c573d6000803e3d6000fd5b5050505061212381856129f590919063ffffffff16565b61215f816001600160a01b031663eef49ee36040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ca57600080fd5b925050600101612042565b50600e5461217e908263ffffffff6128b116565b600e55601354604080516001600160a01b0390921680835260208084018381529284018890527fea7a4e14e72ba7db7e2fd406278900badf50b2ce7d9def39d613cc08054c537b9391928992899290919060608301908590850280828437600083820152604051601f909101601f1916909201829003965090945050505050a1505050505050565b612217600f3363ffffffff61298716565b6122525760405162461bcd60e51b8152600401808060200182810382526022815260200180612e0e6022913960400191505060405180910390fd5b60035460ff16156122945760405162461bcd60e51b815260040180806020018281038252603c815260200180612ea5603c913960400191505060405180910390fd5b61229c612968565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b1580156122d457600080fd5b505afa1580156122e8573d6000803e3d6000fd5b5050600e5461111c925090508263ffffffff6128b116565b6123086126f3565b60088190556040805182815290517f5a2f2eae84f9e787d8159d363a776fa2b61d084686190cdc5a2c1ea833480b099181900360200190a150565b600b54600c5482565b60035460ff161561238e5760405162461bcd60e51b815260040180806020018281038252603c815260200180612ea5603c913960400191505060405180910390fd5b60005b81811015611fcb5760008383838181106123a757fe5b905060200201356001600160a01b03169050806001600160a01b031663c8db233e336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050600060405180830381600087803b15801561241157600080fd5b505af1158015612425573d6000803e3d6000fd5b5050505061243d81601161277090919063ffffffff16565b604080516001600160a01b038316815290517f16e62064e42f5aec62df22ae895ef539f153e0d4ea290e2cc4e0e8f708f2fbbc9181900360200190a150600101612391565b61248a6126f3565b600b8190556040805182815290517fdf7a26ae2e2eb953b81fd76b72fcdc74ebff7c21faa8f8f55323183d9785f52d9181900360200190a150565b6060611666600f848463ffffffff612a4716565b60035460ff161561251b5760405162461bcd60e51b815260040180806020018281038252603c815260200180612ea5603c913960400191505060405180910390fd5b61252c600f8263ffffffff61298716565b612574576040805162461bcd60e51b8152602060048201526014602482015273139bdd08185b881858dd1a5d99481b585c9ad95d60621b604482015290519081900360640190fd5b6000816001600160a01b03166302d05d3f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156125af57600080fd5b505afa1580156125c3573d6000803e3d6000fd5b505050506040513d60208110156125d957600080fd5b50519050336001600160a01b0382161461263a576040805162461bcd60e51b815260206004820152601960248201527f53656e646572206e6f74206d61726b65742063726561746f7200000000000000604482015290519081900360640190fd5b6040805163130cffa560e21b815233600482015290516001600160a01b03841691634c33fe9491602480830192600092919082900301818387803b15801561268157600080fd5b505af1158015612695573d6000803e3d6000fd5b505050506126ad82600f61277090919063ffffffff16565b604080516001600160a01b038416815290517f996fafab197beb99fff6fdc975bb6cf90352f2c733c76ef37c2e27f17d7d424b9181900360200190a15050565b600e5481565b6000546001600160a01b0316331461273c5760405162461bcd60e51b815260040180806020018281038252602f815260200180612e51602f913960400191505060405180910390fd5b565b6000612751600f8363ffffffff61298716565b80612768575061276860118363ffffffff61298716565b90505b919050565b61277a8282612987565b6127c1576040805162461bcd60e51b815260206004820152601360248201527222b632b6b2b73a103737ba1034b71039b2ba1760691b604482015290519081900360640190fd5b6001600160a01b03811660009081526001830160205260409020548254600019018082146128605760008460000182815481106127fa57fe5b60009182526020909120015485546001600160a01b039091169150819086908590811061282357fe5b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815260018601909152604090208290555b835484908061286b57fe5b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0394909416815260019490940190925250506040812055565b600082820183811015611666576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082821115612962576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006129826b53797374656d53746174757360a01b612c8b565b905090565b815460009061299857506000611669565b6001600160a01b0382166000908152600184016020526040902054801515806129ed5750826001600160a01b0316846000016000815481106129d657fe5b6000918252602090912001546001600160a01b0316145b949350505050565b6129ff8282612987565b6113ec5781546001600160a01b038216600081815260018086016020908152604083208590559084018655858252902090910180546001600160a01b03191690911790555050565b825460609083830190811115612a5b575083545b838111612a78575050604080516000815260208101909152612b16565b604080518583038082526020808202830101909252606090828015612aa7578160200160208202803883390190505b50905060005b82811015612b10578760000187820181548110612ac657fe5b9060005260206000200160009054906101000a90046001600160a01b0316828281518110612af057fe5b6001600160a01b0390921660209283029190910190910152600101612aad565b50925050505b9392505050565b600080612b28612d6f565b9050806001600160a01b031663ac82f608846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612b6e57600080fd5b505afa158015612b82573d6000803e3d6000fd5b505050506040513d6020811015612b9857600080fd5b505115612c485782631cd554d160e21b1415612bb857600091505061276b565b6000816001600160a01b031663728dec29856040518263ffffffff1660e01b81526004018082815260200191505060a06040518083038186803b158015612bfe57600080fd5b505afa158015612c12573d6000803e3d6000fd5b505050506040513d60a0811015612c2857600080fd5b505190508015612c3d5760009250505061276b565b60019250505061276b565b50600092915050565b60006129827842696e6172794f7074696f6e4d61726b6574466163746f727960381b612c8b565b60006129826814de5b9d1a1cd554d160ba1b5b600081815260046020908152604080832054815170026b4b9b9b4b7339030b2323932b9b99d1607d1b9381019390935260318084018690528251808503909101815260519093019091526001600160a01b03169081612d685760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612d2d578181015183820152602001612d15565b50505050905090810190601f168015612d5a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5092915050565b60006129826c45786368616e6765526174657360981b612c8b56fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e65727368697043726561746f7220736b6577206c696d6974206d757374206265206e6f2067726561746572207468616e20312e546f74616c20666565206d757374206265206c657373207468616e20313030252e5065726d6974746564206f6e6c7920666f7220616374697665206d61726b6574732e5065726d6974746564206f6e6c7920666f72206b6e6f776e206d61726b6574732e4f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e4f6e6c79207065726d697474656420666f72206d6967726174696e67206d616e616765722e5468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e747261637420697320706175736564526566756e6420666565206d757374206265206e6f2067726561746572207468616e20313030252ea265627a7a72315820020cfc36f9d5dc23de8fcf224831b4dad9b06476a079d24438bbfbcd7e40a9e964736f6c6343000510003243726561746f7220736b6577206c696d6974206d757374206265206e6f2067726561746572207468616e20312e546f74616c20666565206d757374206265206c657373207468616e20313030252e4f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e526566756e6420666565206d757374206265206e6f2067726561746572207468616e20313030252e000000000000000000000000b64ff7a4a33acdf48d97dab0d764afd0f6176882000000000000000000000000242a3df52c375bee81b1c668741d7c63af68fdd20000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000eff1000000000000000000000000000000000000000000000000000000000003c2670000000000000000000000000000000000000000000000003635c9adc5dea0000000000000000000000000000000000000000000000000000000b1a2bc2ec50000000000000000000000000000000000000000000000000000001c6bf52634000000000000000000000000000000000000000000000000000000071afd498d000000000000000000000000000000000000000000000000000000b1a2bc2ec50000

Library Used

SafeDecimalMath : 0x1a60e2e2a8be0bc2b6381dd31fd3fd5f9a28de4c

Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading