Contract 0x30efe43c4bb21b7f282218923504ddb4118f1815

 
Txn Hash Method
Block
From
To
Value
0x912a284c3c0f5b6b789624ea1d2ce8f5bcec6c1d7c5a2d0b411e871fc2b7020e0x6080604015079592021-12-24 8:51:54826 days 6 hrs agoThales: Deployer IN  Create: ThalesAMM0 ETH0.0239817807190.001
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ThalesAMM

Compiler Version
v0.5.16+commit.9c3226ce

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 14 : ThalesAMM.sol
pragma solidity ^0.5.16;

import "synthetix-2.50.4-ovm/contracts/interfaces/IERC20.sol";
import "openzeppelin-solidity-2.3.0/contracts/math/Math.sol";
import "synthetix-2.50.4-ovm/contracts/SafeDecimalMath.sol";
import "@openzeppelin/upgrades-core/contracts/Initializable.sol";

import "../utils/proxy/ProxyReentrancyGuard.sol";
import "../utils/proxy/ProxyOwned.sol";
import "../utils/proxy/ProxyPausable.sol";

import "../interfaces/IPriceFeed.sol";
import "../interfaces/IBinaryOptionMarket.sol";
import "../interfaces/IBinaryOptionMarketManager.sol";
import "../interfaces/IBinaryOption.sol";
import "./DeciMath.sol";

contract ThalesAMM is ProxyOwned, ProxyPausable, ProxyReentrancyGuard, Initializable {
    using SafeMath for uint;
    using SafeDecimalMath for uint;

    DeciMath public deciMath;

    uint private constant ONE = 1e18;
    uint private constant ONE_PERCENT = 1e16;

    uint private constant MIN_SUPPORTED_PRICE = 10e16;
    uint private constant MAX_SUPPORTED_PRICE = 90e16;

    IPriceFeed public priceFeed;
    IERC20 public sUSD;
    address public manager;

    uint public capPerMarket;
    uint public min_spread;
    uint public max_spread;

    mapping(bytes32 => uint) public impliedVolatilityPerAsset;

    uint public minimalTimeLeftToMaturity;

    struct MarketSkew {
        uint longs;
        uint shorts;
    }

    enum Position {Long, Short}

    mapping(address => uint) public spentOnMarket;

    function initialize(
        address _owner,
        IPriceFeed _priceFeed,
        IERC20 _sUSD,
        uint _capPerMarket,
        DeciMath _deciMath,
        uint _min_spread,
        uint _max_spread,
        uint _minimalTimeLeftToMaturity
    ) public initializer {
        setOwner(_owner);
        initNonReentrant();
        priceFeed = _priceFeed;
        sUSD = _sUSD;
        capPerMarket = _capPerMarket;
        deciMath = _deciMath;
        min_spread = _min_spread;
        max_spread = _max_spread;
        minimalTimeLeftToMaturity = _minimalTimeLeftToMaturity;
    }

    function availableToBuyFromAMM(address market, Position position) public view returns (uint) {
        if (isMarketInAMMTrading(market)) {
            uint basePrice = price(market, position);
            // ignore extremes
            if (basePrice <= MIN_SUPPORTED_PRICE || basePrice >= MAX_SUPPORTED_PRICE) {
                return 0;
            }
            uint balance = _balanceOfPositionOnMarket(market, position);
            uint buy_max_price = basePrice.mul(ONE.add(max_spread)).div(ONE);
            // ignore extremes
            if (buy_max_price >= ONE.sub(ONE_PERCENT) || buy_max_price <= ONE_PERCENT) {
                return 0;
            }
            uint divider_max_price = ONE.sub(buy_max_price);
            uint additionalBufferFromSelling = balance.mul(buy_max_price).div(ONE);
            if (capPerMarket.add(additionalBufferFromSelling) <= spentOnMarket[market]) {
                return 0;
            }
            uint availableUntilCapSUSD = capPerMarket.add(additionalBufferFromSelling).sub(spentOnMarket[market]);

            return balance.add(availableUntilCapSUSD.div(divider_max_price).mul(ONE));
        } else {
            return 0;
        }
    }

    function buyFromAmmQuote(
        address market,
        Position position,
        uint amount
    ) public view returns (uint) {
        if (amount > availableToBuyFromAMM(market, position)) {
            return 0;
        }
        uint basePrice = price(market, position);
        return amount.mul(basePrice.mul(ONE.add(_buyPriceImpact(market, position, amount))).div(ONE)).div(ONE);
    }

    function buyPriceImpact(
        address market,
        Position position,
        uint amount
    ) public view returns (uint) {
        if (amount > availableToBuyFromAMM(market, position)) {
            return 0;
        }
        return _buyPriceImpact(market, position, amount);
    }

    function availableToSellToAMM(address market, Position position) public view returns (uint) {
        if (isMarketInAMMTrading(market)) {
            uint basePrice = price(market, position);
            // ignore extremes
            if (basePrice <= MIN_SUPPORTED_PRICE || basePrice >= MAX_SUPPORTED_PRICE) {
                return 0;
            }
            uint sell_max_price = basePrice.mul(ONE.sub(max_spread)).div(ONE);
            require(sell_max_price > 0, "div by zero sell_max_price");
            (IBinaryOption long, IBinaryOption short) = IBinaryOptionMarket(market).options();
            uint balanceOfTheOtherSide =
                position == Position.Long ? short.balanceOf(address(this)) : long.balanceOf(address(this));

            // can burn straight away balanceOfTheOtherSide
            uint willPay = balanceOfTheOtherSide.mul(sell_max_price).div(ONE);
            uint usdAvailable = capPerMarket.add(balanceOfTheOtherSide).sub(spentOnMarket[market]).sub(willPay);
            return usdAvailable.div(sell_max_price).mul(ONE).add(balanceOfTheOtherSide);
        } else return 0;
    }

    function sellToAmmQuote(
        address market,
        Position position,
        uint amount
    ) public view returns (uint) {
        if (amount > availableToSellToAMM(market, position)) {
            return 0;
        }
        uint basePrice = price(market, position);
        return amount.mul(basePrice.mul(ONE.sub(_sellPriceImpact(market, position, amount))).div(ONE)).div(ONE);
    }

    function sellPriceImpact(
        address market,
        Position position,
        uint amount
    ) public view returns (uint) {
        if (amount > availableToSellToAMM(market, position)) {
            return 0;
        }
        return _sellPriceImpact(market, position, amount);
    }

    function price(address market, Position position) public view returns (uint) {
        if (isMarketInAMMTrading(market)) {
            // add price calculation
            IBinaryOptionMarket marketContract = IBinaryOptionMarket(market);
            (uint maturity, uint destructino) = marketContract.times();

            uint timeLeftToMaturity = maturity - block.timestamp;
            uint timeLeftToMaturityInDays = timeLeftToMaturity.mul(ONE).div(86400);
            uint oraclePrice = marketContract.oraclePrice();

            (bytes32 key, uint strikePrice, uint finalPrice) = marketContract.oracleDetails();

            if (position == Position.Long) {
                return
                    calculateOdds(oraclePrice, strikePrice, timeLeftToMaturityInDays, impliedVolatilityPerAsset[key]).div(
                        1e2
                    );
            } else {
                return
                    ONE.sub(
                        calculateOdds(oraclePrice, strikePrice, timeLeftToMaturityInDays, impliedVolatilityPerAsset[key])
                            .div(1e2)
                    );
            }
        } else return 0;
    }

    function calculateOdds(
        uint price,
        uint strike,
        uint timeLeftInDays,
        uint volatility
    ) public view returns (uint) {
        uint vt = volatility.div(100).mul(sqrt(timeLeftInDays.div(365))).div(1e9);
        bool direction = strike >= price;
        uint lnBase = strike >= price ? strike.mul(ONE).div(price) : price.mul(ONE).div(strike);
        uint d1 = deciMath.ln(lnBase, 99).mul(ONE).div(vt);
        uint y = ONE.mul(ONE).div(ONE.add(d1.mul(2316419).div(1e7)));
        uint d2 = d1.mul(d1).div(2).div(ONE);
        uint z = _expneg(d2).mul(3989423).div(1e7);

        uint y5 = deciMath.pow(y, 5 * ONE).mul(1330274).div(1e6);
        uint y4 = deciMath.pow(y, 4 * ONE).mul(1821256).div(1e6);
        uint y3 = deciMath.pow(y, 3 * ONE).mul(1781478).div(1e6);
        uint y2 = deciMath.pow(y, 2 * ONE).mul(356538).div(1e6);
        uint y1 = y.mul(3193815).div(1e7);
        uint x1 = y5.add(y3).add(y1).sub(y4).sub(y2);
        uint x = ONE.sub(z.mul(x1).div(ONE));
        uint result = ONE.mul(1e2).sub(x.mul(1e2));
        if (direction) {
            return result;
        } else {
            return ONE.mul(1e2).sub(result);
        }
    }

    function isMarketInAMMTrading(address market) public view returns (bool) {
        if (IBinaryOptionMarketManager(manager).isActiveMarket(market)) {
            IBinaryOptionMarket marketContract = IBinaryOptionMarket(market);
            (bytes32 key, uint strikePrice, uint finalPrice) = marketContract.oracleDetails();
            //check if asset is supported
            if (impliedVolatilityPerAsset[key] == 0) {
                return false;
            }
            // add price calculation
            (uint maturity, uint destructino) = marketContract.times();

            uint timeLeftToMaturity = maturity - block.timestamp;
            return timeLeftToMaturity > minimalTimeLeftToMaturity;
        } else {
            return false;
        }
    }

    function canExerciseMaturedMarket(address market) public view returns (bool) {
        if (
            IBinaryOptionMarketManager(manager).isKnownMarket(market) &&
            (IBinaryOptionMarket(market).phase() == IBinaryOptionMarket.Phase.Maturity)
        ) {
            (IBinaryOption long, IBinaryOption short) = IBinaryOptionMarket(market).options();
            if ((long.balanceOf(address(this)) > 0) || (short.balanceOf(address(this)) > 0)) {
                return true;
            }
        }
        return false;
    }

    // write methods

    function buyFromAMM(
        address market,
        Position position,
        uint amount,
        uint expectedPayout,
        uint additionalSlippage
    ) public nonReentrant notPaused {
        require(isMarketInAMMTrading(market), "Market is not in Trading phase");

        uint availableToBuyFromAMMATM = availableToBuyFromAMM(market, position);
        require(availableToBuyFromAMMATM > 0 && amount <= availableToBuyFromAMMATM, "Not enough liquidity.");

        uint sUSDPaid = buyFromAmmQuote(market, position, amount);
        require(sUSD.balanceOf(msg.sender) >= sUSDPaid, "You dont have enough sUSD.");
        require(sUSD.allowance(msg.sender, address(this)) >= sUSDPaid, "No allowance.");
        require(sUSDPaid.mul(ONE).div(expectedPayout) <= ONE.add(additionalSlippage), "Slippage too high");

        sUSD.transferFrom(msg.sender, address(this), sUSDPaid);

        uint toMint = _getMintableAmount(market, position, amount);
        if (toMint > 0) {
            require(sUSD.balanceOf(address(this)) >= toMint, "Not enough sUSD in contract.");
            IBinaryOptionMarket(market).mint(toMint);
            spentOnMarket[market] = spentOnMarket[market].add(toMint);
        }

        (IBinaryOption long, IBinaryOption short) = IBinaryOptionMarket(market).options();
        IBinaryOption target = position == Position.Long ? long : short;
        IERC20(address(target)).transfer(msg.sender, amount);

        if (spentOnMarket[market] <= sUSDPaid) {
            spentOnMarket[market] = 0;
        } else {
            spentOnMarket[market] = spentOnMarket[market].sub(sUSDPaid);
        }

        emit BoughtFromAmm(msg.sender, market, position, amount, sUSDPaid, address(sUSD), address(target));
    }

    function sellToAMM(
        address market,
        Position position,
        uint amount,
        uint expectedPayout,
        uint additionalSlippage
    ) public nonReentrant notPaused {
        require(isMarketInAMMTrading(market), "Market is not in Trading phase");

        uint availableToSellToAMMATM = availableToSellToAMM(market, position);
        require(availableToSellToAMMATM > 0 && amount <= availableToSellToAMMATM, "Not enough liquidity.");

        uint pricePaid = sellToAmmQuote(market, position, amount);
        require(expectedPayout.mul(ONE).div(pricePaid) <= (ONE.add(additionalSlippage)), "Slippage too high");

        (IBinaryOption long, IBinaryOption short) = IBinaryOptionMarket(market).options();
        IBinaryOption target = position == Position.Long ? long : short;

        require(target.balanceOf(msg.sender) >= amount, "You dont have enough options.");
        require(IERC20(address(target)).allowance(msg.sender, address(this)) >= amount, "No allowance.");

        //transfer options first to have max burn available
        IERC20(address(target)).transferFrom(msg.sender, address(this), amount);
        uint sUSDFromBurning = IBinaryOptionMarket(market).getMaximumBurnable(address(this));
        if (sUSDFromBurning > 0) {
            IBinaryOptionMarket(market).burnOptionsMaximum();
        }

        require(sUSD.balanceOf(address(this)) >= pricePaid, "Not enough sUSD in contract.");

        sUSD.transfer(msg.sender, pricePaid);

        spentOnMarket[market] = spentOnMarket[market].add(pricePaid);
        if (spentOnMarket[market] <= sUSDFromBurning) {
            spentOnMarket[market] = 0;
        } else {
            spentOnMarket[market] = spentOnMarket[market].sub(sUSDFromBurning);
        }

        emit SoldToAMM(msg.sender, market, position, amount, pricePaid, address(sUSD), address(target));
    }

    function exerciseMaturedMarket(address market) external {
        require(
            IBinaryOptionMarket(market).phase() == IBinaryOptionMarket.Phase.Maturity,
            "Market is not in Maturity phase"
        );
        require(IBinaryOptionMarketManager(manager).isKnownMarket(market), "Unknown market");
        require(canExerciseMaturedMarket(market), "No options to exercise");
        IBinaryOptionMarket(market).exerciseOptions();
    }

    // setters
    function setMinimalTimeLeftToMaturity(uint _minimalTimeLeftToMaturity) public onlyOwner {
        minimalTimeLeftToMaturity = _minimalTimeLeftToMaturity;
        emit SetMinimalTimeLeftToMaturity(_minimalTimeLeftToMaturity);
    }

    function setMinSpread(uint _spread) public onlyOwner {
        min_spread = _spread;
        emit SetMinSpread(_spread);
    }

    function setMaxSpread(uint _spread) public onlyOwner {
        max_spread = _spread;
        emit SetMaxSpread(_spread);
    }

    function setImpliedVolatilityPerAsset(bytes32 asset, uint _impliedVolatility) public onlyOwner {
        impliedVolatilityPerAsset[asset] = _impliedVolatility;
        emit SetImpliedVolatilityPerAsset(asset, _impliedVolatility);
    }

    function setCapPerMarket(uint _capPerMarket) public onlyOwner {
        capPerMarket = _capPerMarket;
        emit SetCapPerMarket(_capPerMarket);
    }

    function setPriceFeed(IPriceFeed _priceFeed) public onlyOwner {
        priceFeed = _priceFeed;
        emit SetPriceFeed(address(_priceFeed));
    }

    function setSUSD(IERC20 _sUSD) public onlyOwner {
        sUSD = _sUSD;
        emit SetSUSD(address(sUSD));
    }

    function setBinaryOptionsMarketManager(address _manager) public onlyOwner {
        if (address(_manager) != address(0)) {
            sUSD.approve(address(_manager), 0);
        }
        manager = _manager;
        sUSD.approve(manager, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        emit SetBinaryOptionsMarketManager(_manager);
    }

    // Internal functions

    function _buyPriceImpact(
        address market,
        Position position,
        uint amount
    ) internal view returns (uint) {
        (IBinaryOption long, IBinaryOption short) = IBinaryOptionMarket(market).options();
        uint balancePosition = position == Position.Long ? long.balanceOf(address(this)) : short.balanceOf(address(this));
        uint balanceOtherSide = position == Position.Long ? short.balanceOf(address(this)) : long.balanceOf(address(this));
        uint balancePositionAfter = balancePosition > amount ? balancePosition.sub(amount) : 0;
        uint balanceOtherSideAfter =
            balancePosition > amount ? balanceOtherSide : balanceOtherSide.add(amount.sub(balancePosition));
        uint pricePaid = _minimalBuyPrice(market, position).mul(amount).div(ONE);
        if (balancePositionAfter >= balanceOtherSideAfter) {
            //minimal price impact as it will balance the AMM exposure
            return min_spread;
        } else {
            uint basePriceOtherSide = price(market, position == Position.Long ? Position.Short : Position.Long);
            uint skew = balanceOtherSideAfter.sub(balancePositionAfter);
            uint maxPossibleSkew = capPerMarket.mul(ONE).div(basePriceOtherSide);
            return min_spread.add(max_spread.sub(min_spread).mul(skew.mul(ONE).div(maxPossibleSkew)).div(ONE));
        }
    }

    function _sellPriceImpact(
        address market,
        Position position,
        uint amount
    ) internal view returns (uint) {
        (IBinaryOption long, IBinaryOption short) = IBinaryOptionMarket(market).options();
        uint balancePosition = position == Position.Long ? long.balanceOf(address(this)) : short.balanceOf(address(this));
        uint balanceOtherSide = position == Position.Long ? short.balanceOf(address(this)) : long.balanceOf(address(this));
        uint balancePositionAfter = balancePosition.add(amount);
        uint pricePaid = _minimalSellPrice(market, position).mul(amount).div(ONE);
        if (balancePositionAfter < balanceOtherSide) {
            //minimal price impact as it will balance the AMM exposure
            return min_spread;
        } else {
            uint basePrice = price(market, position);
            uint skew = balancePositionAfter.sub(balanceOtherSide);
            require(basePrice > 0, "div by zero basePrice");
            uint maxPossibleSkew = capPerMarket.mul(ONE).div(basePrice);
            require(maxPossibleSkew > 0, "div by zero maxPossibleSkew");
            return min_spread.add(max_spread.sub(min_spread).mul(skew.mul(ONE).div(maxPossibleSkew)).div(ONE));
        }
    }

    function _getMintableAmount(
        address market,
        Position position,
        uint amount
    ) internal view returns (uint mintable) {
        uint availableInContract = _balanceOfPositionOnMarket(market, position);
        mintable = 0;
        if (availableInContract < amount) {
            mintable = amount.sub(availableInContract);
        }
    }

    function _minimalBuyPrice(address market, Position position) internal view returns (uint) {
        return price(market, position).mul(ONE.add(min_spread)).div(ONE);
    }

    function _minimalSellPrice(address market, Position position) internal view returns (uint) {
        return price(market, position).mul(ONE.sub(min_spread)).div(ONE);
    }

    function _balanceOfPositionOnMarket(address market, Position position) internal view returns (uint) {
        (IBinaryOption long, IBinaryOption short) = IBinaryOptionMarket(market).options();
        uint balance = position == Position.Long ? long.balanceOf(address(this)) : short.balanceOf(address(this));
        return balance;
    }

    function _expneg(uint x) internal view returns (uint result) {
        result = (ONE * ONE) / _expNegPow(x);
    }

    function _expNegPow(uint x) internal view returns (uint result) {
        uint e = 2718280000000000000;
        result = deciMath.pow(e, x);
    }

    function sqrt(uint y) internal pure returns (uint z) {
        if (y > 3) {
            z = y;
            uint x = y / 2 + 1;
            while (x < z) {
                z = x;
                x = (y / x + x) / 2;
            }
        } else if (y != 0) {
            z = 1;
        }
    }

    function retrieveSUSD(address payable account) external onlyOwner {
        sUSD.transfer(account, sUSD.balanceOf(address(this)));
    }

    // events
    event SoldToAMM(
        address seller,
        address market,
        Position position,
        uint amount,
        uint sUSDPaid,
        address susd,
        address asset
    );
    event BoughtFromAmm(
        address buyer,
        address market,
        Position position,
        uint amount,
        uint sUSDPaid,
        address susd,
        address asset
    );

    event SetBinaryOptionsMarketManager(address _manager);
    event SetSUSD(address sUSD);
    event SetPriceFeed(address _priceFeed);
    event SetCapPerMarket(uint _capPerMarket);
    event SetImpliedVolatilityPerAsset(bytes32 asset, uint _impliedVolatility);
    event SetMaxSpread(uint _spread);
    event SetMinSpread(uint _spread);
    event SetMinimalTimeLeftToMaturity(uint _minimalTimeLeftToMaturity);
}

File 2 of 14 : IERC20.sol
pragma solidity >=0.4.24;

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

File 3 of 14 : Math.sol
pragma solidity ^0.5.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}

File 4 of 14 : SafeDecimalMath.sol
pragma solidity ^0.5.16;

// Libraries
import "openzeppelin-solidity-2.3.0/contracts/math/SafeMath.sol";

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

    // Computes `a - b`, setting the value to 0 if b > a.
    function floorsub(uint a, uint b) internal pure returns (uint) {
        return b >= a ? 0 : a - b;
    }
}

File 5 of 14 : Initializable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.4.24 <0.7.0;


/**
 * @title Initializable
 *
 * @dev Helper contract to support initializer functions. To use it, replace
 * the constructor with a function that has the `initializer` modifier.
 * WARNING: Unlike constructors, initializer functions must be manually
 * invoked. This applies both to deploying an Initializable contract, as well
 * as extending an Initializable contract via inheritance.
 * WARNING: When used with inheritance, manual care must be taken to not invoke
 * a parent initializer twice, or ensure that all initializers are idempotent,
 * because this is not dealt with automatically as with constructors.
 */
contract Initializable {

  /**
   * @dev Indicates that the contract has been initialized.
   */
  bool private initialized;

  /**
   * @dev Indicates that the contract is in the process of being initialized.
   */
  bool private initializing;

  /**
   * @dev Modifier to use in the initializer function of a contract.
   */
  modifier initializer() {
    require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");

    bool isTopLevelCall = !initializing;
    if (isTopLevelCall) {
      initializing = true;
      initialized = true;
    }

    _;

    if (isTopLevelCall) {
      initializing = false;
    }
  }

  /// @dev Returns true if and only if the function is running in the constructor
  function isConstructor() private view returns (bool) {
    // extcodesize checks the size of the code stored in an address, and
    // address returns the current address. Since the code is still not
    // deployed when running a constructor, any checks on its code size will
    // yield zero, making it an effective way to detect if a contract is
    // under construction or not.
    address self = address(this);
    uint256 cs;
    assembly { cs := extcodesize(self) }
    return cs == 0;
  }

  // Reserved storage space to allow for layout changes in the future.
  uint256[50] private ______gap;
}

File 6 of 14 : ProxyReentrancyGuard.sol
pragma solidity ^0.5.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the `nonReentrant` modifier
 * available, which can be aplied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 */
contract ProxyReentrancyGuard {
    /// @dev counter to allow mutex lock with only one SSTORE operation
    uint256 private _guardCounter;
    bool private _initialized;

    function initNonReentrant() public {
        require(!_initialized, "Already initialized");
        _initialized = true;
        _guardCounter = 1;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _guardCounter += 1;
        uint256 localCounter = _guardCounter;
        _;
        require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call");
    }
}

File 7 of 14 : ProxyOwned.sol
pragma solidity ^0.5.16;

// Clone of syntetix contract without constructor
contract ProxyOwned {
    address public owner;
    address public nominatedOwner;
    bool private _initialized;
    bool private _transferredAtInit;

    function setOwner(address _owner) public {
        require(_owner != address(0), "Owner address cannot be 0");
        require(!_initialized, "Already initialized, use nominateNewOwner");
        _initialized = true;
        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);
    }

    function transferOwnershipAtInit(address proxyAddress) external onlyOwner {
        require(proxyAddress != address(0), "Invalid address");
        require(!_transferredAtInit, "Already transferred");
        owner = proxyAddress;
        _transferredAtInit = true;
        emit OwnerChanged(owner, proxyAddress);
    }

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

File 8 of 14 : ProxyPausable.sol
pragma solidity ^0.5.16;

// Inheritance
import "./ProxyOwned.sol";

// Clone of syntetix contract without constructor

contract ProxyPausable is ProxyOwned {
    uint public lastPauseTime;
    bool public paused;

    

    /**
     * @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");
        _;
    }
}

File 9 of 14 : IPriceFeed.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.24;

interface IPriceFeed {
     // Structs
    struct RateAndUpdatedTime {
        uint216 rate;
        uint40 time;
    }
    
    // Mutative functions
    function addAggregator(bytes32 currencyKey, address aggregatorAddress) external;

    function removeAggregator(bytes32 currencyKey) external;

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

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

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

    function getRates() external view returns (uint[] memory);

    function getCurrencies() external view returns (bytes32[] memory);
}

File 10 of 14 : IBinaryOptionMarket.sol
pragma solidity ^0.5.16;

import "../interfaces/IBinaryOptionMarketManager.sol";
import "../interfaces/IBinaryOption.sol";
import "../interfaces/IPriceFeed.sol";

interface IBinaryOptionMarket {
    /* ========== TYPES ========== */

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

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

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

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

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

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

    function deposited() external view returns (uint);

    function creator() external view returns (address);

    function resolved() external view returns (bool);

    function phase() external view returns (Phase);

    function oraclePrice() external view returns (uint);

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

    function canResolve() external view returns (bool);

    function result() external view returns (Side);

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

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

    function getMaximumBurnable(address account) external view returns (uint amount);

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

    function mint(uint value) external;

    function exerciseOptions() external returns (uint);

    function burnOptions(uint amount) external;

    function burnOptionsMaximum() external;
}

File 11 of 14 : IBinaryOptionMarketManager.sol
pragma solidity ^0.5.16;

import "../interfaces/IBinaryOptionMarket.sol";

interface IBinaryOptionMarketManager {
    /* ========== VIEWS / VARIABLES ========== */

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

    function capitalRequirement() external view returns (uint);

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

    function isActiveMarket(address candidate) external view returns (bool);

    function isKnownMarket(address candidate) external view returns (bool);

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

    function createMarket(
        bytes32 oracleKey,
        uint strikePrice,
        uint maturity,
        uint initialMint, // initial sUSD to mint options for,
        bool customMarket,
        address customOracle
    ) external returns (IBinaryOptionMarket);

    function resolveMarket(address market) external;

    function expireMarkets(address[] calldata market) external;

    function transferSusdTo(
        address sender,
        address receiver,
        uint amount
    ) external;
}

File 12 of 14 : IBinaryOption.sol
pragma solidity ^0.5.16;

import "../interfaces/IBinaryOptionMarket.sol";
import "synthetix-2.50.4-ovm/contracts/interfaces/IERC20.sol";

interface IBinaryOption {
    /* ========== VIEWS / VARIABLES ========== */

    function market() external view returns (IBinaryOptionMarket);

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

    function totalSupply() external view returns (uint);

}

File 13 of 14 : DeciMath.sol
pragma solidity ^0.5.0;

contract DeciMath {
    // Abbreviation: DP stands for 'Decimal Places'

    uint constant TEN38 = 10**38;
    uint constant TEN30 = 10**30;
    uint constant TEN20 = 10**20;
    uint constant TEN19 = 10**19;
    uint constant TEN18 = 10**18;
    uint constant TEN17 = 10**17;
    uint constant TEN12 = 10**12;
    uint constant TEN11 = 10**11;
    uint constant TEN10 = 10**10;
    uint constant TEN9 = 10**9;
    uint constant TEN8 = 10**8;
    uint constant TEN7 = 10**7;

    // ln(2) - used in ln(x). 30 DP.
    uint constant LN2 = 693147180559945309417232121458;

    // 1 / ln(2) - used in exp(x). 30 DP.
    uint constant ONE_OVER_LN2 = 1442695040888963407359924681002;

    /***** LOOKUP TABLES *****/

    // Lookup table arrays (LUTs) for log_2(x)
    uint[100] public table_log_2;
    uint[100] public table2_log_2;

    // Lookup table for pow2(). Table contains 39 arrays, each array contains 10 uint slots.
    uint[10][39] public table_pow2;

    // LUT flags
    bool LUT1_isSet = false;
    bool LUT2_isSet = false;
    bool LUT3_1_isSet = false;
    bool LUT3_2_isSet = false;
    bool LUT3_3_isSet = false;
    bool LUT3_4_isSet = false;

    /******  BASIC MATH OPERATORS ******/

    // Integer math operators. Identical to Zeppelin's SafeMath
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }
        uint256 c = a * b;
        require(c / a == b, "uint overflow from multiplication");
        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "division by zero");
        uint256 c = a / b;
        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "uint underflow from subtraction");
        uint256 c = a - b;
        return c;
    }

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "uint overflow from multiplication");
        return c;
    }

    // Basic decimal math operators. Inputs and outputs are uint representations of fixed-point decimals.

    // 18 Decimal places
    function decMul18(uint x, uint y) public pure returns (uint decProd) {
        uint prod_xy = mul(x, y);
        decProd = add(prod_xy, TEN18 / 2) / TEN18;
    }

    function decDiv18(uint x, uint y) public pure returns (uint decQuotient) {
        uint prod_xTEN18 = mul(x, TEN18);
        decQuotient = add(prod_xTEN18, y / 2) / y;
    }

    // 30 Decimal places
    function decMul30(uint x, uint y) public pure returns (uint decProd) {
        uint prod_xy = mul(x, y);
        decProd = add(prod_xy, TEN30 / 2) / TEN30;
    }

    // 38 Decimal places
    function decMul38(uint x, uint y) public pure returns (uint decProd) {
        uint prod_xy = mul(x, y);
        decProd = add(prod_xy, TEN38 / 2) / TEN38;
    }

    /****** HELPER FUNCTIONS ******/

    function convert38To18DP(uint x) public pure returns (uint y) {
        uint digit = (x % TEN20) / TEN19; // grab 20th digit from-right
        return chopAndRound(x, digit, 20);
    }

    function convert38To30DP(uint x) public pure returns (uint y) {
        uint digit = (x % TEN8) / TEN7; // grab 8th digit from-right
        return chopAndRound(x, digit, 8);
    }

    function convert30To20DP(uint x) public pure returns (uint y) {
        uint digit = (x % TEN10) / TEN9; // grab 10th digit from-right
        return chopAndRound(x, digit, 10);
    }

    function convert30To18DP(uint x) public pure returns (uint y) {
        uint digit = (x % TEN12) / TEN11; // grab 12th digit from-right
        return chopAndRound(x, digit, 12);
    }

    // Chop the last digits, and round the resulting number
    function chopAndRound(
        uint num,
        uint digit,
        uint positionOfChop
    ) public pure returns (uint chopped) {
        if (digit < 5) {
            chopped = div(num, 10**positionOfChop); // round down
        } else if (digit >= 5) {
            chopped = div(num, 10**positionOfChop) + 1; // round up
        }
        return chopped;
    }

    // return the floor of a fixed-point 20DP number
    function floor(uint x) public pure returns (uint num) {
        num = x - (x % TEN20);
        return num;
    }

    function countDigits(uint num) public view returns (uint) {
        uint digits = 0;

        while (num != 0) {
            num /= 10; // When num < 10, yields 0 due to EVM floor division
            digits++;
        }
        return digits;
    }

    /****** MATH FUNCTIONS ******/

    // b^x for integer exponent. Use highly performant 'exponentiation-by-squaring' algorithm. O(log(n)) operations.

    // b^x - integer base, integer exponent
    function powBySquare(uint x, uint n) public pure returns (uint) {
        if (n == 0) return 1;

        uint y = 1;

        while (n > 1)
            if (n % 2 == 0) {
                x = mul(x, x);
                n = n / 2;
            } else if (n % 2 != 0) {
                y = mul(x, y);
                x = mul(x, x);
                n = (n - 1) / 2;
            }
        return mul(x, y);
    }

    // b^x - fixed-point 18 DP base, integer exponent
    function powBySquare18(uint base, uint n) public pure returns (uint) {
        if (n == 0) return TEN18;

        uint y = TEN18;

        while (n > 1) {
            if (n % 2 == 0) {
                base = decMul18(base, base);
                n = n / 2;
            } else if (n % 2 != 0) {
                y = decMul18(base, y);
                base = decMul18(base, base);
                n = (n - 1) / 2;
            }
        }
        return decMul18(base, y);
    }

    // b^x - fixed-point 38 DP base, integer exponent n
    function powBySquare38(uint base, uint n) public pure returns (uint) {
        if (n == 0) return TEN38;

        uint y = TEN38;

        while (n > 1) {
            if (n % 2 == 0) {
                base = decMul38(base, base);
                n = n / 2;
            } else if (n % 2 != 0) {
                y = decMul38(base, y);
                base = decMul38(base, base);
                n = (n - 1) / 2;
            }
        }
        return decMul38(base, y);
    }

    /* exp(x) function. Input 18 DP, output 18 DP.  Uses identities:

    A) e^x = 2^(x / ln(2))

    and

    B) 2^y = (2^r) * 2^(y - r); where r = floor(y) - 1, and (y - r) is in range [1,2[

    */
    function exp(uint x) public view returns (uint num) {
        uint intExponent; // 20 DP
        uint decExponent; // 20 DP
        uint coefficient; // 38 DP

        x = mul(x, TEN12); // make x 30DP
        x = decMul30(ONE_OVER_LN2, x);
        x = convert30To20DP(x);

        // if x < 1, do: (2^-1) * 2^(1 + x)
        if (x < TEN20 && x >= 0) {
            decExponent = add(TEN20, x);
            coefficient = TEN38 / 2;
            num = decMul38(coefficient, pow2(decExponent));
        }
        // Use identity B)
        else {
            intExponent = floor(x) - TEN20;
            decExponent = x - intExponent; // decimal exponent in range [1,2[
            coefficient = powBySquare(2, div(intExponent, TEN20));
            num = mul(coefficient, pow2(decExponent)); //  use normal mul to avoid overflow, as coeff. is an int
        }

        return convert38To18DP(num);
    }

    // Base-2 logarithm function, for x in range [1,2[. For use in ln(x). Input 18 DP, output 30 DP.
    function log_2(uint x, uint accuracy) public view _onlyLUT1andLUT2AreSet returns (uint) {
        require(x >= TEN18 && x < 2 * TEN18, "input x must be within range [1,2[");
        uint prod = mul(x, TEN20); // make x 38 DP
        uint newProd = TEN38;
        uint output = 0;

        for (uint i = 1; i <= accuracy; i++) {
            newProd = decMul38(table_log_2[i], prod);

            if (newProd >= TEN38) {
                prod = newProd;
                output += table2_log_2[i];
            }
        }
        return convert38To30DP(output);
    }

    // pow2(x) function, for use in exp(x). Uses 2D-array LUT. Valid for x in range [1,2[. Input 20DP, output 38DP
    function pow2(uint x) public view _onlyLUT3isSet returns (uint) {
        require(x >= TEN20 && x < 2 * TEN20, "input x must be within range [1,2[");
        uint x_38dp = x * TEN18;
        uint prod = 2 * TEN38;
        uint fractPart = x_38dp % TEN38;
        uint digitsLength = countDigits(fractPart);

        // loop backwards through mantissa digits - multiply each by the Lookup-table value
        for (uint i = 0; i < digitsLength; i++) {
            uint digit = (fractPart % (10**(i + 1))) / (10**i); // grab the i'th digit from right

            if (digit == 0) continue; // Save gas - skip the step if digit = 0 and there would be no resultant change to prod

            // computer i'th term, and new product
            uint term = table_pow2[37 - i][digit];
            prod = decMul38(prod, term);
        }
        return prod;
    }

    /* Natural log function ln(x). Input 18 DP, output 18 DP. Uses identities:

    A) ln(x) = log_2(x) * ln(2)

    and

    B) log_2(x) = log_2(2^q * y)           y in range [1,2[
                = q + log_2(y)

    The algorithm finds q and y by repeated division by powers-of-two.
    */
    function ln(uint x, uint accuracy) public view returns (uint) {
        require(x >= TEN18, "input must be >= 1");
        uint count = 0; // track
        uint TWO = mul(TEN18, 2);

        /* Calculate q. Use branches to divide by powers-of-two, until output is in range [1,2[. Branch approach is more performant
        than simple successive division by 2. As max input of ln(x) is ~= 2^132, starting division at 2^30 yields sufficiently few operations for large x. */
        while (x >= 2 * TEN18) {
            if (x >= 1073741824 * TEN18) {
                // start at 2^30
                x = decDiv18(x, 1073741824 * TEN18);
                count += 30;
            } else if (x >= 1048576 * TEN18) {
                x = decDiv18(x, 1048576 * TEN18);
                count += 20;
            } else if (x >= 32768 * TEN18) {
                x = decDiv18(x, 32768 * TEN18);
                count += 15;
            } else if (x >= 1024 * TEN18) {
                x = decDiv18(x, 1024 * TEN18);
                count += 10;
            } else if (x >= 512 * TEN18) {
                x = decDiv18(x, 512 * TEN18);
                count += 9;
            } else if (x >= 256 * TEN18) {
                x = decDiv18(x, 256 * TEN18);
                count += 8;
            } else if (x >= 128 * TEN18) {
                x = decDiv18(x, 128 * TEN18);
                count += 7;
            } else if (x >= 64 * TEN18) {
                x = decDiv18(x, 64 * TEN18);
                count += 6;
            } else if (x >= 32 * TEN18) {
                x = decDiv18(x, 32 * TEN18);
                count += 5;
            } else if (x >= 16 * TEN18) {
                x = decDiv18(x, 16 * TEN18);
                count += 4;
            } else if (x >= 8 * TEN18) {
                x = decDiv18(x, 8 * TEN18);
                count += 3;
            } else if (x >= 4 * TEN18) {
                x = decDiv18(x, 4 * TEN18);
                count += 2;
            } else if (x >= 2 * TEN18) {
                x = decDiv18(x, 2 * TEN18);
                count += 1;
            }
        }

        uint q = count * TEN30;
        uint output = decMul30(LN2, add(q, log_2(x, accuracy)));

        return convert30To18DP(output);
    }

    /* pow(b, x) function for 18 DP base and exponent. Output 18 DP.

    Uses identity:  b^x = exp (x * ln(b)).

    For b < 1, rewrite b^x as:
    b^x = exp( x * (-ln(1/b)) ) = 1/exp(x * ln(1/b)).

     Thus, we avoid passing argument y < 1 to ln(y), and z < 0 to exp(z).   */
    function pow(uint base, uint x) public view returns (uint power) {
        if (base >= TEN18) {
            return exp(decMul18(x, ln(base, 70)));
        }

        if (base < TEN18) {
            uint exponent = decMul18(x, ln(decDiv18(TEN18, base), 70));
            return decDiv18(TEN18, exp(exponent));
        }
    }

    // Taylor series implementation of exp(x) - lower accuracy and higher gas cost than exp(x). 18 DP input and output.
    function exp_taylor(uint x) public pure returns (uint) {
        uint tolerance = 1;
        uint term = TEN18;
        uint sum = TEN18;
        uint i = 0;

        while (term > tolerance) {
            i += TEN18;
            term = decDiv18(decMul18(term, x), i);
            sum += term;
        }
        return sum;
    }

    /* Lookup Tables (LUTs). 38 DP fixed-point numbers. */

    // LUT1 for log_2(x). The i'th term is 1/(2^(1/2^i))
    function setLUT1() public {
        table_log_2[0] = 0;
        table_log_2[1] = 70710678118654752440084436210484903928;
        table_log_2[2] = 84089641525371454303112547623321489504;
        table_log_2[3] = 91700404320467123174354159479414442804;
        table_log_2[4] = 95760328069857364693630563514791544393;
        table_log_2[5] = 97857206208770013450916112581343574560;
        table_log_2[6] = 98922801319397548412912495906558366777;
        table_log_2[7] = 99459942348363317565247768622216631446;
        table_log_2[8] = 99729605608547012625765991384792260112;
        table_log_2[9] = 99864711289097017358812131808592040806;
        table_log_2[10] = 99932332750265075236028365984373804116;
        table_log_2[11] = 99966160649624368394219686876281565561;
        table_log_2[12] = 99983078893192906311748078019767389868;
        table_log_2[13] = 99991539088661349753372497156418872723;
        table_log_2[14] = 99995769454843113254396753730099797524;
        table_log_2[15] = 99997884705049192982650067113039327478;
        table_log_2[16] = 99998942346931446424221059225315431670;
        table_log_2[17] = 99999471172067428300770241277030532519;
        table_log_2[18] = 99999735585684139498225234636504270993;
        table_log_2[19] = 99999867792754675970531776759801063698;
        table_log_2[20] = 99999933896355489526178052900624509795;
        table_log_2[21] = 99999966948172282646511738368820575117;
        table_log_2[22] = 99999983474084775793885880947314828005;
        table_log_2[23] = 99999991737042046514572235133214264694;
        table_log_2[24] = 99999995868520937911689915196095249000;
        table_log_2[25] = 99999997934260447619445466250978583193;
        table_log_2[26] = 99999998967130218475622805194415901619;
        table_log_2[27] = 99999999483565107904286413727651274869;
        table_log_2[28] = 99999999741782553618761958785587923503;
        table_log_2[29] = 99999999870891276726035667265628464908;
        table_log_2[30] = 99999999935445638342181505587572099682;
        table_log_2[31] = 99999999967722819165881670780794171827;
        table_log_2[32] = 99999999983861409581638564886938948308;
        table_log_2[33] = 99999999991930704790493714817578668739;
        table_log_2[34] = 99999999995965352395165465502313349139;
        table_log_2[35] = 99999999997982676197562384774537267778;
        table_log_2[36] = 99999999998991338098776105393113730880;
        table_log_2[37] = 99999999999495669049386780948018133274;
        table_log_2[38] = 99999999999747834524693072536874382794;
        table_log_2[39] = 99999999999873917262346456784153520336;
        table_log_2[40] = 99999999999936958631173208521005842390;
        table_log_2[41] = 99999999999968479315586599292735191749;
        table_log_2[42] = 99999999999984239657793298404425663513;
        table_log_2[43] = 99999999999992119828896648891727348666;
        table_log_2[44] = 99999999999996059914448324368242303560;
        table_log_2[45] = 99999999999998029957224162164715809087;
        table_log_2[46] = 99999999999999014978612081077506568870;
        table_log_2[47] = 99999999999999507489306040537540450517;
        table_log_2[48] = 99999999999999753744653020268467016779;
        table_log_2[49] = 99999999999999876872326510134157706270;
        table_log_2[50] = 99999999999999938436163255067059902605;
        table_log_2[51] = 99999999999999969218081627533525213670;
        table_log_2[52] = 99999999999999984609040813766761422427;
        table_log_2[53] = 99999999999999992304520406883380415111;
        table_log_2[54] = 99999999999999996152260203441690133530;
        table_log_2[55] = 99999999999999998076130101720845048259;
        table_log_2[56] = 99999999999999999038065050860422519503;
        table_log_2[57] = 99999999999999999519032525430211258595;
        table_log_2[58] = 99999999999999999759516262715105629008;
        table_log_2[59] = 99999999999999999879758131357552814432;
        table_log_2[60] = 99999999999999999939879065678776407198;
        table_log_2[61] = 99999999999999999969939532839388203594;
        table_log_2[62] = 99999999999999999984969766419694101796;
        table_log_2[63] = 99999999999999999992484883209847050898;
        table_log_2[64] = 99999999999999999996242441604923525449;
        table_log_2[65] = 99999999999999999998121220802461762724;
        table_log_2[66] = 99999999999999999999060610401230881362;
        table_log_2[67] = 99999999999999999999530305200615440681;
        table_log_2[68] = 99999999999999999999765152600307720341;
        table_log_2[69] = 99999999999999999999882576300153860170;
        table_log_2[70] = 99999999999999999999941288150076930085;
        table_log_2[71] = 99999999999999999999970644075038465043;
        table_log_2[72] = 99999999999999999999985322037519232521;
        table_log_2[73] = 99999999999999999999992661018759616261;
        table_log_2[74] = 99999999999999999999996330509379808130;
        table_log_2[75] = 99999999999999999999998165254689904065;
        table_log_2[76] = 99999999999999999999999082627344952033;
        table_log_2[77] = 99999999999999999999999541313672476016;
        table_log_2[78] = 99999999999999999999999770656836238008;
        table_log_2[79] = 99999999999999999999999885328418119004;
        table_log_2[80] = 99999999999999999999999942664209059502;
        table_log_2[81] = 99999999999999999999999971332104529751;
        table_log_2[82] = 99999999999999999999999985666052264876;
        table_log_2[83] = 99999999999999999999999992833026132438;
        table_log_2[84] = 99999999999999999999999996416513066219;
        table_log_2[85] = 99999999999999999999999998208256533109;
        table_log_2[86] = 99999999999999999999999999104128266555;
        table_log_2[87] = 99999999999999999999999999552064133277;
        table_log_2[88] = 99999999999999999999999999776032066639;
        table_log_2[89] = 99999999999999999999999999888016033319;
        table_log_2[90] = 99999999999999999999999999944008016660;
        table_log_2[91] = 99999999999999999999999999972004008330;
        table_log_2[92] = 99999999999999999999999999986002004165;
        table_log_2[93] = 99999999999999999999999999993001002082;
        table_log_2[94] = 99999999999999999999999999996500501041;
        table_log_2[95] = 99999999999999999999999999998250250521;
        table_log_2[96] = 99999999999999999999999999999125125260;
        table_log_2[97] = 99999999999999999999999999999562562630;
        table_log_2[98] = 99999999999999999999999999999781281315;
        table_log_2[99] = 99999999999999999999999999999890640658;

        LUT1_isSet = true;
    }

    // LUT2 for log_2(x). The i'th term is 1/(2^i)
    function setLUT2() public {
        table2_log_2[0] = 200000000000000000000000000000000000000;
        table2_log_2[1] = 50000000000000000000000000000000000000;
        table2_log_2[2] = 25000000000000000000000000000000000000;
        table2_log_2[3] = 12500000000000000000000000000000000000;
        table2_log_2[4] = 6250000000000000000000000000000000000;
        table2_log_2[5] = 3125000000000000000000000000000000000;
        table2_log_2[6] = 1562500000000000000000000000000000000;
        table2_log_2[7] = 781250000000000000000000000000000000;
        table2_log_2[8] = 390625000000000000000000000000000000;
        table2_log_2[9] = 195312500000000000000000000000000000;
        table2_log_2[10] = 97656250000000000000000000000000000;
        table2_log_2[11] = 48828125000000000000000000000000000;
        table2_log_2[12] = 24414062500000000000000000000000000;
        table2_log_2[13] = 12207031250000000000000000000000000;
        table2_log_2[14] = 6103515625000000000000000000000000;
        table2_log_2[15] = 3051757812500000000000000000000000;
        table2_log_2[16] = 1525878906250000000000000000000000;
        table2_log_2[17] = 762939453125000000000000000000000;
        table2_log_2[18] = 381469726562500000000000000000000;
        table2_log_2[19] = 190734863281250000000000000000000;
        table2_log_2[20] = 95367431640625000000000000000000;
        table2_log_2[21] = 47683715820312500000000000000000;
        table2_log_2[22] = 23841857910156250000000000000000;
        table2_log_2[23] = 11920928955078125000000000000000;
        table2_log_2[24] = 5960464477539062500000000000000;
        table2_log_2[25] = 2980232238769531250000000000000;
        table2_log_2[26] = 1490116119384765625000000000000;
        table2_log_2[27] = 745058059692382812500000000000;
        table2_log_2[28] = 372529029846191406250000000000;
        table2_log_2[29] = 186264514923095703125000000000;
        table2_log_2[30] = 93132257461547851562500000000;
        table2_log_2[31] = 46566128730773925781250000000;
        table2_log_2[32] = 23283064365386962890625000000;
        table2_log_2[33] = 11641532182693481445312500000;
        table2_log_2[34] = 5820766091346740722656250000;
        table2_log_2[35] = 2910383045673370361328125000;
        table2_log_2[36] = 1455191522836685180664062500;
        table2_log_2[37] = 727595761418342590332031250;
        table2_log_2[38] = 363797880709171295166015625;
        table2_log_2[39] = 181898940354585647583007812;
        table2_log_2[40] = 90949470177292823791503906;
        table2_log_2[41] = 45474735088646411895751953;
        table2_log_2[42] = 22737367544323205947875976;
        table2_log_2[43] = 11368683772161602973937988;
        table2_log_2[44] = 5684341886080801486968994;
        table2_log_2[45] = 2842170943040400743484497;
        table2_log_2[46] = 1421085471520200371742248;
        table2_log_2[47] = 710542735760100185871124;
        table2_log_2[48] = 355271367880050092935562;
        table2_log_2[49] = 177635683940025046467781;
        table2_log_2[50] = 88817841970012523233890;
        table2_log_2[51] = 44408920985006261616945;
        table2_log_2[52] = 22204460492503130808472;
        table2_log_2[53] = 11102230246251565404236;
        table2_log_2[54] = 5551115123125782702118;
        table2_log_2[55] = 2775557561562891351059;
        table2_log_2[56] = 1387778780781445675529;
        table2_log_2[57] = 693889390390722837764;
        table2_log_2[58] = 346944695195361418882;
        table2_log_2[59] = 173472347597680709441;
        table2_log_2[60] = 86736173798840354720;
        table2_log_2[61] = 43368086899420177360;
        table2_log_2[62] = 21684043449710088680;
        table2_log_2[63] = 10842021724855044340;
        table2_log_2[64] = 5421010862427522170;
        table2_log_2[65] = 2710505431213761085;
        table2_log_2[66] = 1355252715606880542;
        table2_log_2[67] = 677626357803440271;
        table2_log_2[68] = 338813178901720135;
        table2_log_2[69] = 169406589450860067;
        table2_log_2[70] = 84703294725430033;
        table2_log_2[71] = 42351647362715016;
        table2_log_2[72] = 21175823681357508;
        table2_log_2[73] = 10587911840678754;
        table2_log_2[74] = 5293955920339377;
        table2_log_2[75] = 2646977960169688;
        table2_log_2[76] = 1323488980084844;
        table2_log_2[77] = 661744490042422;
        table2_log_2[78] = 330872245021211;
        table2_log_2[79] = 165436122510605;
        table2_log_2[80] = 82718061255302;
        table2_log_2[81] = 41359030627651;
        table2_log_2[82] = 20679515313825;
        table2_log_2[83] = 10339757656912;
        table2_log_2[84] = 5169878828456;
        table2_log_2[85] = 2584939414228;
        table2_log_2[86] = 1292469707114;
        table2_log_2[87] = 646234853557;
        table2_log_2[88] = 323117426778;
        table2_log_2[89] = 161558713389;
        table2_log_2[90] = 80779356694;
        table2_log_2[91] = 40389678347;
        table2_log_2[92] = 20194839173;
        table2_log_2[93] = 10097419586;
        table2_log_2[94] = 5048709793;
        table2_log_2[95] = 2524354896;
        table2_log_2[96] = 1262177448;
        table2_log_2[97] = 631088724;
        table2_log_2[98] = 315544362;
        table2_log_2[99] = 157772181;

        LUT2_isSet = true;
    }

    /* LUT for pow2() function. Table contains 39 arrays, each array contains 10 uint slots.

    table_pow2[i][d] = (2^(1 / 10^(i + 1))) ** d.
    d ranges from 0 to 9.

    LUT-setting is split into four separate setter functions to keep gas costs under block limit.
    */
    function setLUT3_1() public {
        table_pow2[0][0] = 100000000000000000000000000000000000000;
        table_pow2[0][1] = 107177346253629316421300632502334202291;
        table_pow2[0][2] = 114869835499703500679862694677792758944;
        table_pow2[0][3] = 123114441334491628449939306916774310988;
        table_pow2[0][4] = 131950791077289425937400197122964013303;
        table_pow2[0][5] = 141421356237309504880168872420969807857;
        table_pow2[0][6] = 151571656651039808234725980130644523868;
        table_pow2[0][7] = 162450479271247104521941876555056330257;
        table_pow2[0][8] = 174110112659224827827254003495949219796;
        table_pow2[0][9] = 186606598307361483196268653229988433405;
        table_pow2[1][0] = 100000000000000000000000000000000000000;
        table_pow2[1][1] = 100695555005671880883269821411323978545;
        table_pow2[1][2] = 101395947979002913869016599962823042584;
        table_pow2[1][3] = 102101212570719324976409517478306437354;
        table_pow2[1][4] = 102811382665606650934634495879263497655;
        table_pow2[1][5] = 103526492384137750434778819421124619773;
        table_pow2[1][6] = 104246576084112139095471141872690784007;
        table_pow2[1][7] = 104971668362306726904934732174028851665;
        table_pow2[1][8] = 105701804056138037449949421408611430989;
        table_pow2[1][9] = 106437018245335988793865835140404338206;
        table_pow2[2][0] = 100000000000000000000000000000000000000;
        table_pow2[2][1] = 100069338746258063253756863930385919571;
        table_pow2[2][2] = 100138725571133452908322477441877746756;
        table_pow2[2][3] = 100208160507963279436035132489114568295;
        table_pow2[2][4] = 100277643590107768843673305907248072983;
        table_pow2[2][5] = 100347174850950278700477431086959080340;
        table_pow2[2][6] = 100416754323897314177285298995922943429;
        table_pow2[2][7] = 100486382042378544096788794597976421668;
        table_pow2[2][8] = 100556058039846816994919680064517944020;
        table_pow2[2][9] = 100625782349778177193372141519657470417;
        table_pow2[3][0] = 100000000000000000000000000000000000000;
        table_pow2[3][1] = 100006931712037656919243991260264256542;
        table_pow2[3][2] = 100013863904561631568466376833067115945;
        table_pow2[3][3] = 100020796577605229875592540103010552992;
        table_pow2[3][4] = 100027729731201760077218879711834041246;
        table_pow2[3][5] = 100034663365384532718772839985089028270;
        table_pow2[3][6] = 100041597480186860654672952451661760537;
        table_pow2[3][7] = 100048532075642059048488888456913382370;
        table_pow2[3][8] = 100055467151783445373101522870206286485;
        table_pow2[3][9] = 100062402708644339410863008887585747065;
        table_pow2[4][0] = 100000000000000000000000000000000000000;
        table_pow2[4][1] = 100000693149582830565320908980056168150;
        table_pow2[4][2] = 100001386303970224572423685307245831542;
        table_pow2[4][3] = 100002079463162215324119782522433627138;
        table_pow2[4][4] = 100002772627158836123451492465145260129;
        table_pow2[4][5] = 100003465795960120273691946873622208121;
        table_pow2[4][6] = 100004158969566101078345118984887516084;
        table_pow2[4][7] = 100004852147976811841145825134822682163;
        table_pow2[4][8] = 100005545331192285866059726358255634403;
        table_pow2[4][9] = 100006238519212556457283329989059798485;
        table_pow2[5][0] = 100000000000000000000000000000000000000;
        table_pow2[5][1] = 100000069314742078650777263622740703038;
        table_pow2[5][2] = 100000138629532202636248826052225815048;
        table_pow2[5][3] = 100000207944370371989717187112633071811;
        table_pow2[5][4] = 100000277259256586744484869711682067979;
        table_pow2[5][5] = 100000346574190846933854419840650257373;
        table_pow2[5][6] = 100000415889173152591128406574388953292;
        table_pow2[5][7] = 100000485204203503749609422071339328833;
        table_pow2[5][8] = 100000554519281900442600081573548417222;
        table_pow2[5][9] = 100000623834408342703403023406685112154;
        table_pow2[6][0] = 100000000000000000000000000000000000000;
        table_pow2[6][1] = 100000006931472045825965603683996211583;
        table_pow2[6][2] = 100000013862944572104978428035962521332;
        table_pow2[6][3] = 100000020794417578837071775524560348874;
        table_pow2[6][4] = 100000027725891066022278948620759465140;
        table_pow2[6][5] = 100000034657365033660633249797837992529;
        table_pow2[6][6] = 100000041588839481752167981531382405066;
        table_pow2[6][7] = 100000048520314410296916446299287528561;
        table_pow2[6][8] = 100000055451789819294911946581756540768;
        table_pow2[6][9] = 100000062383265708746187784861300971552;
        table_pow2[7][0] = 100000000000000000000000000000000000000;
        table_pow2[7][1] = 100000000693147182962210384558650120894;
        table_pow2[7][2] = 100000001386294370728950941601779822006;
        table_pow2[7][3] = 100000002079441563300221704431854648481;
        table_pow2[7][4] = 100000002772588760676022706351340376300;
        table_pow2[7][5] = 100000003465735962856353980662703012279;
        table_pow2[7][6] = 100000004158883169841215560668408794069;
        table_pow2[7][7] = 100000004852030381630607479670924190156;
        table_pow2[7][8] = 100000005545177598224529770972715899860;
        table_pow2[7][9] = 100000006238324819622982467876250853339;
        table_pow2[8][0] = 100000000000000000000000000000000000000;
        table_pow2[8][1] = 100000000069314718080017181643183694247;
        table_pow2[8][2] = 100000000138629436208079664711489996172;
        table_pow2[8][3] = 100000000207944154384187449238221371011;
        table_pow2[8][4] = 100000000277258872608340535256680284018;
        table_pow2[8][5] = 100000000346573590880538922800169200474;
        table_pow2[8][6] = 100000000415888309200782611901990585682;
        table_pow2[8][7] = 100000000485203027569071602595446904968;
        table_pow2[8][8] = 100000000554517745985405894913840623680;
        table_pow2[8][9] = 100000000623832464449785488890474207190;
        table_pow2[9][0] = 100000000000000000000000000000000000000;
        table_pow2[9][1] = 100000000006931471805839679601136972338;
        table_pow2[9][2] = 100000000013862943612159812216225448565;
        table_pow2[9][3] = 100000000020794415418960397845298731148;
        table_pow2[9][4] = 100000000027725887226241436488390122551;
        table_pow2[9][5] = 100000000034657359034002928145532925240;
        table_pow2[9][6] = 100000000041588830842244872816760441679;
        table_pow2[9][7] = 100000000048520302650967270502105974334;
        table_pow2[9][8] = 100000000055451774460170121201602825670;
        table_pow2[9][9] = 100000000062383246269853424915284298153;
        table_pow2[10][0] = 100000000000000000000000000000000000000;
        table_pow2[10][1] = 100000000000693147180562347574486828679;
        table_pow2[10][2] = 100000000001386294361129499679112872675;
        table_pow2[10][3] = 100000000002079441541701456313878165290;
        table_pow2[10][4] = 100000000002772588722278217478782739826;
        table_pow2[10][5] = 100000000003465735902859783173826629587;
        table_pow2[10][6] = 100000000004158883083446153399009867874;
        table_pow2[10][7] = 100000000004852030264037328154332487990;
        table_pow2[10][8] = 100000000005545177444633307439794523238;
        table_pow2[10][9] = 100000000006238324625234091255396006920;

        LUT3_1_isSet = true;
    }

    function setLUT3_2() public {
        table_pow2[11][0] = 100000000000000000000000000000000000000;
        table_pow2[11][1] = 100000000000069314718056018553592419128;
        table_pow2[11][2] = 100000000000138629436112085152486230109;
        table_pow2[11][3] = 100000000000207944154168199796681432977;
        table_pow2[11][4] = 100000000000277258872224362486178027765;
        table_pow2[11][5] = 100000000000346573590280573220976014506;
        table_pow2[11][6] = 100000000000415888308336832001075393234;
        table_pow2[11][7] = 100000000000485203026393138826476163982;
        table_pow2[11][8] = 100000000000554517744449493697178326784;
        table_pow2[11][9] = 100000000000623832462505896613181881671;
        table_pow2[12][0] = 100000000000000000000000000000000000000;
        table_pow2[12][1] = 100000000000006931471805599693320679280;
        table_pow2[12][2] = 100000000000013862943611199867094372479;
        table_pow2[12][3] = 100000000000020794415416800521321079596;
        table_pow2[12][4] = 100000000000027725887222401656000800631;
        table_pow2[12][5] = 100000000000034657359028003271133535584;
        table_pow2[12][6] = 100000000000041588830833605366719284456;
        table_pow2[12][7] = 100000000000048520302639207942758047246;
        table_pow2[12][8] = 100000000000055451774444810999249823955;
        table_pow2[12][9] = 100000000000062383246250414536194614582;
        table_pow2[13][0] = 100000000000000000000000000000000000000;
        table_pow2[13][1] = 100000000000000693147180559947711682302;
        table_pow2[13][2] = 100000000000001386294361119900227894743;
        table_pow2[13][3] = 100000000000002079441541679857548637323;
        table_pow2[13][4] = 100000000000002772588722239819673910042;
        table_pow2[13][5] = 100000000000003465735902799786603712900;
        table_pow2[13][6] = 100000000000004158883083359758338045898;
        table_pow2[13][7] = 100000000000004852030263919734876909035;
        table_pow2[13][8] = 100000000000005545177444479716220302311;
        table_pow2[13][9] = 100000000000006238324625039702368225726;
        table_pow2[14][0] = 100000000000000000000000000000000000000;
        table_pow2[14][1] = 100000000000000069314718055994554964374;
        table_pow2[14][2] = 100000000000000138629436111989157974049;
        table_pow2[14][3] = 100000000000000207944154167983809029026;
        table_pow2[14][4] = 100000000000000277258872223978508129304;
        table_pow2[14][5] = 100000000000000346573590279973255274883;
        table_pow2[14][6] = 100000000000000415888308335968050465764;
        table_pow2[14][7] = 100000000000000485203026391962893701947;
        table_pow2[14][8] = 100000000000000554517744447957784983430;
        table_pow2[14][9] = 100000000000000623832462503952724310215;
        table_pow2[15][0] = 100000000000000000000000000000000000000;
        table_pow2[15][1] = 100000000000000006931471805599453334399;
        table_pow2[15][2] = 100000000000000013862943611198907149251;
        table_pow2[15][3] = 100000000000000020794415416798361444556;
        table_pow2[15][4] = 100000000000000027725887222397816220313;
        table_pow2[15][5] = 100000000000000034657359027997271476524;
        table_pow2[15][6] = 100000000000000041588830833596727213188;
        table_pow2[15][7] = 100000000000000048520302639196183430305;
        table_pow2[15][8] = 100000000000000055451774444795640127875;
        table_pow2[15][9] = 100000000000000062383246250395097305898;
        table_pow2[16][0] = 100000000000000000000000000000000000000;
        table_pow2[16][1] = 100000000000000000693147180559945311819;
        table_pow2[16][2] = 100000000000000001386294361119890628444;
        table_pow2[16][3] = 100000000000000002079441541679835949872;
        table_pow2[16][4] = 100000000000000002772588722239781276105;
        table_pow2[16][5] = 100000000000000003465735902799726607143;
        table_pow2[16][6] = 100000000000000004158883083359671942985;
        table_pow2[16][7] = 100000000000000004852030263919617283632;
        table_pow2[16][8] = 100000000000000005545177444479562629083;
        table_pow2[16][9] = 100000000000000006238324625039507979339;
        table_pow2[17][0] = 100000000000000000000000000000000000000;
        table_pow2[17][1] = 100000000000000000069314718055994530966;
        table_pow2[17][2] = 100000000000000000138629436111989061980;
        table_pow2[17][3] = 100000000000000000207944154167983593041;
        table_pow2[17][4] = 100000000000000000277258872223978124151;
        table_pow2[17][5] = 100000000000000000346573590279972655309;
        table_pow2[17][6] = 100000000000000000415888308335967186515;
        table_pow2[17][7] = 100000000000000000485203026391961717769;
        table_pow2[17][8] = 100000000000000000554517744447956249071;
        table_pow2[17][9] = 100000000000000000623832462503950780421;
        table_pow2[18][0] = 100000000000000000000000000000000000000;
        table_pow2[18][1] = 100000000000000000006931471805599453094;
        table_pow2[18][2] = 100000000000000000013862943611198906189;
        table_pow2[18][3] = 100000000000000000020794415416798359285;
        table_pow2[18][4] = 100000000000000000027725887222397812381;
        table_pow2[18][5] = 100000000000000000034657359027997265477;
        table_pow2[18][6] = 100000000000000000041588830833596718574;
        table_pow2[18][7] = 100000000000000000048520302639196171671;
        table_pow2[18][8] = 100000000000000000055451774444795624769;
        table_pow2[18][9] = 100000000000000000062383246250395077867;
        table_pow2[19][0] = 100000000000000000000000000000000000000;
        table_pow2[19][1] = 100000000000000000000693147180559945309;
        table_pow2[19][2] = 100000000000000000001386294361119890619;
        table_pow2[19][3] = 100000000000000000002079441541679835928;
        table_pow2[19][4] = 100000000000000000002772588722239781238;
        table_pow2[19][5] = 100000000000000000003465735902799726547;
        table_pow2[19][6] = 100000000000000000004158883083359671857;
        table_pow2[19][7] = 100000000000000000004852030263919617166;
        table_pow2[19][8] = 100000000000000000005545177444479562475;
        table_pow2[19][9] = 100000000000000000006238324625039507785;
        table_pow2[20][0] = 100000000000000000000000000000000000000;
        table_pow2[20][1] = 100000000000000000000069314718055994531;
        table_pow2[20][2] = 100000000000000000000138629436111989062;
        table_pow2[20][3] = 100000000000000000000207944154167983593;
        table_pow2[20][4] = 100000000000000000000277258872223978124;
        table_pow2[20][5] = 100000000000000000000346573590279972655;
        table_pow2[20][6] = 100000000000000000000415888308335967186;
        table_pow2[20][7] = 100000000000000000000485203026391961717;
        table_pow2[20][8] = 100000000000000000000554517744447956248;
        table_pow2[20][9] = 100000000000000000000623832462503950778;

        LUT3_2_isSet = true;
    }

    function setLUT3_3() public {
        table_pow2[21][0] = 100000000000000000000000000000000000000;
        table_pow2[21][1] = 100000000000000000000006931471805599453;
        table_pow2[21][2] = 100000000000000000000013862943611198906;
        table_pow2[21][3] = 100000000000000000000020794415416798359;
        table_pow2[21][4] = 100000000000000000000027725887222397812;
        table_pow2[21][5] = 100000000000000000000034657359027997265;
        table_pow2[21][6] = 100000000000000000000041588830833596719;
        table_pow2[21][7] = 100000000000000000000048520302639196172;
        table_pow2[21][8] = 100000000000000000000055451774444795625;
        table_pow2[21][9] = 100000000000000000000062383246250395078;
        table_pow2[22][0] = 100000000000000000000000000000000000000;
        table_pow2[22][1] = 100000000000000000000000693147180559945;
        table_pow2[22][2] = 100000000000000000000001386294361119891;
        table_pow2[22][3] = 100000000000000000000002079441541679836;
        table_pow2[22][4] = 100000000000000000000002772588722239781;
        table_pow2[22][5] = 100000000000000000000003465735902799727;
        table_pow2[22][6] = 100000000000000000000004158883083359672;
        table_pow2[22][7] = 100000000000000000000004852030263919617;
        table_pow2[22][8] = 100000000000000000000005545177444479562;
        table_pow2[22][9] = 100000000000000000000006238324625039508;
        table_pow2[23][0] = 100000000000000000000000000000000000000;
        table_pow2[23][1] = 100000000000000000000000069314718055995;
        table_pow2[23][2] = 100000000000000000000000138629436111989;
        table_pow2[23][3] = 100000000000000000000000207944154167984;
        table_pow2[23][4] = 100000000000000000000000277258872223978;
        table_pow2[23][5] = 100000000000000000000000346573590279973;
        table_pow2[23][6] = 100000000000000000000000415888308335967;
        table_pow2[23][7] = 100000000000000000000000485203026391962;
        table_pow2[23][8] = 100000000000000000000000554517744447956;
        table_pow2[23][9] = 100000000000000000000000623832462503951;
        table_pow2[24][0] = 100000000000000000000000000000000000000;
        table_pow2[24][1] = 100000000000000000000000006931471805599;
        table_pow2[24][2] = 100000000000000000000000013862943611199;
        table_pow2[24][3] = 100000000000000000000000020794415416798;
        table_pow2[24][4] = 100000000000000000000000027725887222398;
        table_pow2[24][5] = 100000000000000000000000034657359027997;
        table_pow2[24][6] = 100000000000000000000000041588830833597;
        table_pow2[24][7] = 100000000000000000000000048520302639196;
        table_pow2[24][8] = 100000000000000000000000055451774444796;
        table_pow2[24][9] = 100000000000000000000000062383246250395;
        table_pow2[25][0] = 100000000000000000000000000000000000000;
        table_pow2[25][1] = 100000000000000000000000000693147180560;
        table_pow2[25][2] = 100000000000000000000000001386294361120;
        table_pow2[25][3] = 100000000000000000000000002079441541680;
        table_pow2[25][4] = 100000000000000000000000002772588722240;
        table_pow2[25][5] = 100000000000000000000000003465735902800;
        table_pow2[25][6] = 100000000000000000000000004158883083360;
        table_pow2[25][7] = 100000000000000000000000004852030263920;
        table_pow2[25][8] = 100000000000000000000000005545177444480;
        table_pow2[25][9] = 100000000000000000000000006238324625040;
        table_pow2[26][0] = 100000000000000000000000000000000000000;
        table_pow2[26][1] = 100000000000000000000000000069314718056;
        table_pow2[26][2] = 100000000000000000000000000138629436112;
        table_pow2[26][3] = 100000000000000000000000000207944154168;
        table_pow2[26][4] = 100000000000000000000000000277258872224;
        table_pow2[26][5] = 100000000000000000000000000346573590280;
        table_pow2[26][6] = 100000000000000000000000000415888308336;
        table_pow2[26][7] = 100000000000000000000000000485203026392;
        table_pow2[26][8] = 100000000000000000000000000554517744448;
        table_pow2[26][9] = 100000000000000000000000000623832462504;
        table_pow2[27][0] = 100000000000000000000000000000000000000;
        table_pow2[27][1] = 100000000000000000000000000006931471806;
        table_pow2[27][2] = 100000000000000000000000000013862943611;
        table_pow2[27][3] = 100000000000000000000000000020794415417;
        table_pow2[27][4] = 100000000000000000000000000027725887222;
        table_pow2[27][5] = 100000000000000000000000000034657359028;
        table_pow2[27][6] = 100000000000000000000000000041588830834;
        table_pow2[27][7] = 100000000000000000000000000048520302639;
        table_pow2[27][8] = 100000000000000000000000000055451774445;
        table_pow2[27][9] = 100000000000000000000000000062383246250;
        table_pow2[28][0] = 100000000000000000000000000000000000000;
        table_pow2[28][1] = 100000000000000000000000000000693147181;
        table_pow2[28][2] = 100000000000000000000000000001386294361;
        table_pow2[28][3] = 100000000000000000000000000002079441542;
        table_pow2[28][4] = 100000000000000000000000000002772588722;
        table_pow2[28][5] = 100000000000000000000000000003465735903;
        table_pow2[28][6] = 100000000000000000000000000004158883083;
        table_pow2[28][7] = 100000000000000000000000000004852030264;
        table_pow2[28][8] = 100000000000000000000000000005545177444;
        table_pow2[28][9] = 100000000000000000000000000006238324625;
        table_pow2[29][0] = 100000000000000000000000000000000000000;
        table_pow2[29][1] = 100000000000000000000000000000069314718;
        table_pow2[29][2] = 100000000000000000000000000000138629436;
        table_pow2[29][3] = 100000000000000000000000000000207944154;
        table_pow2[29][4] = 100000000000000000000000000000277258872;
        table_pow2[29][5] = 100000000000000000000000000000346573590;
        table_pow2[29][6] = 100000000000000000000000000000415888308;
        table_pow2[29][7] = 100000000000000000000000000000485203026;
        table_pow2[29][8] = 100000000000000000000000000000554517744;
        table_pow2[29][9] = 100000000000000000000000000000623832463;
        table_pow2[30][0] = 100000000000000000000000000000000000000;
        table_pow2[30][1] = 100000000000000000000000000000006931472;
        table_pow2[30][2] = 100000000000000000000000000000013862944;
        table_pow2[30][3] = 100000000000000000000000000000020794415;
        table_pow2[30][4] = 100000000000000000000000000000027725887;
        table_pow2[30][5] = 100000000000000000000000000000034657359;
        table_pow2[30][6] = 100000000000000000000000000000041588831;
        table_pow2[30][7] = 100000000000000000000000000000048520303;
        table_pow2[30][8] = 100000000000000000000000000000055451774;
        table_pow2[30][9] = 100000000000000000000000000000062383246;

        LUT3_3_isSet = true;
    }

    function setLUT3_4() public {
        table_pow2[31][0] = 100000000000000000000000000000000000000;
        table_pow2[31][1] = 100000000000000000000000000000000693147;
        table_pow2[31][2] = 100000000000000000000000000000001386294;
        table_pow2[31][3] = 100000000000000000000000000000002079442;
        table_pow2[31][4] = 100000000000000000000000000000002772589;
        table_pow2[31][5] = 100000000000000000000000000000003465736;
        table_pow2[31][6] = 100000000000000000000000000000004158883;
        table_pow2[31][7] = 100000000000000000000000000000004852030;
        table_pow2[31][8] = 100000000000000000000000000000005545177;
        table_pow2[31][9] = 100000000000000000000000000000006238325;
        table_pow2[32][0] = 100000000000000000000000000000000000000;
        table_pow2[32][1] = 100000000000000000000000000000000069315;
        table_pow2[32][2] = 100000000000000000000000000000000138629;
        table_pow2[32][3] = 100000000000000000000000000000000207944;
        table_pow2[32][4] = 100000000000000000000000000000000277259;
        table_pow2[32][5] = 100000000000000000000000000000000346574;
        table_pow2[32][6] = 100000000000000000000000000000000415888;
        table_pow2[32][7] = 100000000000000000000000000000000485203;
        table_pow2[32][8] = 100000000000000000000000000000000554518;
        table_pow2[32][9] = 100000000000000000000000000000000623832;
        table_pow2[33][0] = 100000000000000000000000000000000000000;
        table_pow2[33][1] = 100000000000000000000000000000000006931;
        table_pow2[33][2] = 100000000000000000000000000000000013863;
        table_pow2[33][3] = 100000000000000000000000000000000020794;
        table_pow2[33][4] = 100000000000000000000000000000000027726;
        table_pow2[33][5] = 100000000000000000000000000000000034657;
        table_pow2[33][6] = 100000000000000000000000000000000041589;
        table_pow2[33][7] = 100000000000000000000000000000000048520;
        table_pow2[33][8] = 100000000000000000000000000000000055452;
        table_pow2[33][9] = 100000000000000000000000000000000062383;
        table_pow2[34][0] = 100000000000000000000000000000000000000;
        table_pow2[34][1] = 100000000000000000000000000000000000693;
        table_pow2[34][2] = 100000000000000000000000000000000001386;
        table_pow2[34][3] = 100000000000000000000000000000000002079;
        table_pow2[34][4] = 100000000000000000000000000000000002773;
        table_pow2[34][5] = 100000000000000000000000000000000003466;
        table_pow2[34][6] = 100000000000000000000000000000000004159;
        table_pow2[34][7] = 100000000000000000000000000000000004852;
        table_pow2[34][8] = 100000000000000000000000000000000005545;
        table_pow2[34][9] = 100000000000000000000000000000000006238;
        table_pow2[35][0] = 100000000000000000000000000000000000000;
        table_pow2[35][1] = 100000000000000000000000000000000000069;
        table_pow2[35][2] = 100000000000000000000000000000000000139;
        table_pow2[35][3] = 100000000000000000000000000000000000208;
        table_pow2[35][4] = 100000000000000000000000000000000000277;
        table_pow2[35][5] = 100000000000000000000000000000000000347;
        table_pow2[35][6] = 100000000000000000000000000000000000416;
        table_pow2[35][7] = 100000000000000000000000000000000000485;
        table_pow2[35][8] = 100000000000000000000000000000000000555;
        table_pow2[35][9] = 100000000000000000000000000000000000624;
        table_pow2[36][0] = 100000000000000000000000000000000000000;
        table_pow2[36][1] = 100000000000000000000000000000000000007;
        table_pow2[36][2] = 100000000000000000000000000000000000014;
        table_pow2[36][3] = 100000000000000000000000000000000000021;
        table_pow2[36][4] = 100000000000000000000000000000000000028;
        table_pow2[36][5] = 100000000000000000000000000000000000035;
        table_pow2[36][6] = 100000000000000000000000000000000000042;
        table_pow2[36][7] = 100000000000000000000000000000000000049;
        table_pow2[36][8] = 100000000000000000000000000000000000055;
        table_pow2[36][9] = 100000000000000000000000000000000000062;
        table_pow2[37][0] = 100000000000000000000000000000000000000;
        table_pow2[37][1] = 100000000000000000000000000000000000001;
        table_pow2[37][2] = 100000000000000000000000000000000000001;
        table_pow2[37][3] = 100000000000000000000000000000000000002;
        table_pow2[37][4] = 100000000000000000000000000000000000003;
        table_pow2[37][5] = 100000000000000000000000000000000000003;
        table_pow2[37][6] = 100000000000000000000000000000000000004;
        table_pow2[37][7] = 100000000000000000000000000000000000005;
        table_pow2[37][8] = 100000000000000000000000000000000000006;
        table_pow2[37][9] = 100000000000000000000000000000000000006;
        table_pow2[38][0] = 100000000000000000000000000000000000000;
        table_pow2[38][1] = 100000000000000000000000000000000000000;
        table_pow2[38][2] = 100000000000000000000000000000000000000;
        table_pow2[38][3] = 100000000000000000000000000000000000000;
        table_pow2[38][4] = 100000000000000000000000000000000000000;
        table_pow2[38][5] = 100000000000000000000000000000000000000;
        table_pow2[38][6] = 100000000000000000000000000000000000000;
        table_pow2[38][7] = 100000000000000000000000000000000000000;
        table_pow2[38][8] = 100000000000000000000000000000000000001;
        table_pow2[38][9] = 100000000000000000000000000000000000001;

        LUT3_4_isSet = true;
    }

    /***** MODIFIERS *****/

    modifier _onlyLUT1andLUT2AreSet() {
        require(LUT1_isSet == true && LUT2_isSet == true, "Lookup tables 1 & 2 must first be set");
        _;
    }

    modifier _onlyLUT3isSet() {
        require(
            LUT3_1_isSet == true && LUT3_2_isSet == true && LUT3_3_isSet == true && LUT3_4_isSet == true,
            "Lookup table 3 must first be set"
        );
        _;
    }
}

File 14 of 14 : SafeMath.sol
pragma solidity ^0.5.0;

/**
 * @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;
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sUSDPaid","type":"uint256"},{"indexed":false,"internalType":"address","name":"susd","type":"address"},{"indexed":false,"internalType":"address","name":"asset","type":"address"}],"name":"BoughtFromAmm","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":"address","name":"_manager","type":"address"}],"name":"SetBinaryOptionsMarketManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_capPerMarket","type":"uint256"}],"name":"SetCapPerMarket","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"asset","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_impliedVolatility","type":"uint256"}],"name":"SetImpliedVolatilityPerAsset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_spread","type":"uint256"}],"name":"SetMaxSpread","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_spread","type":"uint256"}],"name":"SetMinSpread","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_minimalTimeLeftToMaturity","type":"uint256"}],"name":"SetMinimalTimeLeftToMaturity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_priceFeed","type":"address"}],"name":"SetPriceFeed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sUSD","type":"address"}],"name":"SetSUSD","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sUSDPaid","type":"uint256"},{"indexed":false,"internalType":"address","name":"susd","type":"address"},{"indexed":false,"internalType":"address","name":"asset","type":"address"}],"name":"SoldToAMM","type":"event"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"}],"name":"availableToBuyFromAMM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"}],"name":"availableToSellToAMM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expectedPayout","type":"uint256"},{"internalType":"uint256","name":"additionalSlippage","type":"uint256"}],"name":"buyFromAMM","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"buyFromAmmQuote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"buyPriceImpact","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"strike","type":"uint256"},{"internalType":"uint256","name":"timeLeftInDays","type":"uint256"},{"internalType":"uint256","name":"volatility","type":"uint256"}],"name":"calculateOdds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"canExerciseMaturedMarket","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"capPerMarket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"deciMath","outputs":[{"internalType":"contract DeciMath","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"exerciseMaturedMarket","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"impliedVolatilityPerAsset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"initNonReentrant","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"contract IPriceFeed","name":"_priceFeed","type":"address"},{"internalType":"contract IERC20","name":"_sUSD","type":"address"},{"internalType":"uint256","name":"_capPerMarket","type":"uint256"},{"internalType":"contract DeciMath","name":"_deciMath","type":"address"},{"internalType":"uint256","name":"_min_spread","type":"uint256"},{"internalType":"uint256","name":"_max_spread","type":"uint256"},{"internalType":"uint256","name":"_minimalTimeLeftToMaturity","type":"uint256"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"isMarketInAMMTrading","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":"manager","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"max_spread","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"min_spread","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minimalTimeLeftToMaturity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","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":"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":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"}],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"priceFeed","outputs":[{"internalType":"contract IPriceFeed","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"account","type":"address"}],"name":"retrieveSUSD","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"sUSD","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"sellPriceImpact","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expectedPayout","type":"uint256"},{"internalType":"uint256","name":"additionalSlippage","type":"uint256"}],"name":"sellToAMM","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"sellToAmmQuote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"setBinaryOptionsMarketManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_capPerMarket","type":"uint256"}],"name":"setCapPerMarket","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"asset","type":"bytes32"},{"internalType":"uint256","name":"_impliedVolatility","type":"uint256"}],"name":"setImpliedVolatilityPerAsset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_spread","type":"uint256"}],"name":"setMaxSpread","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_spread","type":"uint256"}],"name":"setMinSpread","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_minimalTimeLeftToMaturity","type":"uint256"}],"name":"setMinimalTimeLeftToMaturity","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","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":"contract IPriceFeed","name":"_priceFeed","type":"address"}],"name":"setPriceFeed","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20","name":"_sUSD","type":"address"}],"name":"setSUSD","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"spentOnMarket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"proxyAddress","type":"address"}],"name":"transferOwnershipAtInit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b5061422d806100206000396000f3fe608060405234801561001057600080fd5b50600436106102695760003560e01c806379ba509711610151578063c2783f92116100c3578063ebc7977211610087578063ebc797721461076a578063efc1525114610772578063f502b003146107a1578063f598df82146107be578063f85de9fa146107db578063fb91d41c146107f857610269565b8063c2783f92146106c1578063c3b83f5f146106f0578063c4dc27d714610716578063ca1d578e1461073c578063df8974d01461076257610269565b80639324cac7116101155780639324cac7146105bb578063a8cd06e8146105c3578063a996798c146105f2578063ad18f0da14610618578063bef648db1461066f578063bf46c0b41461068c57610269565b806379ba509714610545578063851702091461054d5780638875eb841461056a5780638da5cb5b146105ab57806391b4ded9146105b357610269565b806351b9181f116101ea5780636aaa81b6116101ae5780636aaa81b6146104b25780636cfa636e146104ba5780636ed033f8146104c2578063724e78da146104f1578063741bef1a1461051757806375cdc2281461051f57610269565b806351b9181f1461041f57806353a47bb7146104455780635727a0f31461044d5780635c975abb146104875780635ef85b261461048f57610269565b806321ef44c61161023157806321ef44c614610357578063270e13ef1461037d578063316425c3146103b25780633ce1108d146103ba578063481c6a75146103fb57610269565b80630f13aae81461026e57806313af4035146102b55780631627540c146102dd57806316c38b3c146103035780631c37d04b14610322575b600080fd5b6102a36004803603606081101561028457600080fd5b506001600160a01b038135169060ff6020820135169060400135610800565b60408051918252519081900360200190f35b6102db600480360360208110156102cb57600080fd5b50356001600160a01b031661089b565b005b6102db600480360360208110156102f357600080fd5b50356001600160a01b03166109ae565b6102db6004803603602081101561031957600080fd5b50351515610a0a565b6102a36004803603606081101561033857600080fd5b506001600160a01b038135169060ff6020820135169060400135610a84565b6102db6004803603602081101561036d57600080fd5b50356001600160a01b0316610ab2565b6102a36004803603606081101561039357600080fd5b506001600160a01b038135169060ff6020820135169060400135610b14565b6102a3610b7e565b6102db600480360360a08110156103d057600080fd5b506001600160a01b038135169060ff6020820135169060408101359060608101359060800135610b84565b610403611396565b604080516001600160a01b039092168252519081900360200190f35b6102db6004803603602081101561043557600080fd5b50356001600160a01b03166113a5565b6104036115e1565b6104736004803603602081101561046357600080fd5b50356001600160a01b03166115f0565b604080519115158252519081900360200190f35b61047361179c565b6102db600480360360408110156104a557600080fd5b50803590602001356117a5565b6102a36117fe565b610403611804565b6102a3600480360360408110156104d857600080fd5b5080356001600160a01b0316906020013560ff16611813565b6102db6004803603602081101561050757600080fd5b50356001600160a01b0316611a2b565b610403611a87565b6102db6004803603602081101561053557600080fd5b50356001600160a01b0316611a96565b6102db611c0a565b6102db6004803603602081101561056357600080fd5b5035611cc6565b6102db600480360360a081101561058057600080fd5b506001600160a01b038135169060ff6020820135169060408101359060608101359060800135611d07565b61040361243c565b6102a361244b565b610403612451565b6102a3600480360360808110156105d957600080fd5b5080359060208101359060408101359060600135612460565b6102db6004803603602081101561060857600080fd5b50356001600160a01b03166128c3565b6102db600480360361010081101561062f57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135916080820135169060a08101359060c08101359060e0013561299a565b6102db6004803603602081101561068557600080fd5b5035612ab2565b6102a3600480360360608110156106a257600080fd5b506001600160a01b038135169060ff6020820135169060400135612af5565b6102a3600480360360408110156106d757600080fd5b5080356001600160a01b0316906020013560ff16612b1b565b6102db6004803603602081101561070657600080fd5b50356001600160a01b0316612df4565b6102a36004803603602081101561072c57600080fd5b50356001600160a01b0316612f13565b6104736004803603602081101561075257600080fd5b50356001600160a01b0316612f25565b6102a36131a1565b6102db6131a7565b6102a36004803603604081101561078857600080fd5b5080356001600160a01b0316906020013560ff1661320a565b6102a3600480360360208110156107b757600080fd5b50356133c2565b6102db600480360360208110156107d457600080fd5b50356133d4565b6102db600480360360208110156107f157600080fd5b5035613417565b6102a361345a565b600061080c8484612b1b565b82111561081b57506000610894565b60006108278585611813565b9050610890670de0b6b3a7640000610877610883670de0b6b3a764000061087761086a6108558c8c8c613460565b670de0b6b3a76400009063ffffffff61386016565b879063ffffffff6138bd16565b9063ffffffff61391616565b869063ffffffff6138bd16565b9150505b9392505050565b6001600160a01b0381166108f6576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600154600160a01b900460ff161561093f5760405162461bcd60e51b81526004018080602001828103825260298152602001806141166029913960400191505060405180910390fd5b6001805460ff60a01b1916600160a01b179055600080546001600160a01b0383166001600160a01b03199091168117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b6109b6613980565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b610a12613980565b60035460ff1615158115151415610a2857610a81565b6003805460ff1916821515179081905560ff1615610a4557426002555b6003546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b6000610a908484612b1b565b821115610a9f57506000610894565b610aaa848484613460565b949350505050565b610aba613980565b603a80546001600160a01b0319166001600160a01b03838116919091179182905560408051929091168252517f74a8764fc8d62d2d844c8c54426bd94ad034e0e92abdf5280ff75e2cbd678fb6916020908290030190a150565b6000610b20848461320a565b821115610b2f57506000610894565b6000610b3b8585611813565b9050610890670de0b6b3a7640000610877610883670de0b6b3a764000061087761086a610b698c8c8c6139cb565b670de0b6b3a76400009063ffffffff613d6116565b603e5481565b600480546001019081905560035460ff1615610bd15760405162461bcd60e51b815260040180806020018281038252603c8152602001806141bd603c913960400191505060405180910390fd5b610bda866115f0565b610c2b576040805162461bcd60e51b815260206004820152601e60248201527f4d61726b6574206973206e6f7420696e2054726164696e672070686173650000604482015290519081900360640190fd5b6000610c378787612b1b565b9050600081118015610c495750808511155b610c92576040805162461bcd60e51b81526020600482015260156024820152742737ba1032b737bab3b4103634b8bab4b234ba3c9760591b604482015290519081900360640190fd5b6000610c9f888888610800565b9050610cb9670de0b6b3a76400008563ffffffff613d6116565b610cd58261087788670de0b6b3a764000063ffffffff6138bd16565b1115610d1c576040805162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604482015290519081900360640190fd5b600080896001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015610d5757600080fd5b505afa158015610d6b573d6000803e3d6000fd5b505050506040513d6040811015610d8157600080fd5b50805160209091015190925090506000808a6001811115610d9e57fe5b14610da95781610dab565b825b604080516370a0823160e01b815233600482015290519192508a916001600160a01b038416916370a08231916024808301926020929190829003018186803b158015610df657600080fd5b505afa158015610e0a573d6000803e3d6000fd5b505050506040513d6020811015610e2057600080fd5b50511015610e75576040805162461bcd60e51b815260206004820152601d60248201527f596f7520646f6e74206861766520656e6f756768206f7074696f6e732e000000604482015290519081900360640190fd5b60408051636eb1769f60e11b815233600482015230602482015290518a916001600160a01b0384169163dd62ed3e91604480820192602092909190829003018186803b158015610ec457600080fd5b505afa158015610ed8573d6000803e3d6000fd5b505050506040513d6020811015610eee57600080fd5b50511015610f33576040805162461bcd60e51b815260206004820152600d60248201526c27379030b63637bbb0b731b29760991b604482015290519081900360640190fd5b604080516323b872dd60e01b8152336004820152306024820152604481018b905290516001600160a01b038316916323b872dd9160648083019260209291908290030181600087803b158015610f8857600080fd5b505af1158015610f9c573d6000803e3d6000fd5b505050506040513d6020811015610fb257600080fd5b5050604080516314edbee160e31b815230600482015290516000916001600160a01b038e169163a76df70891602480820192602092909190829003018186803b158015610ffe57600080fd5b505afa158015611012573d6000803e3d6000fd5b505050506040513d602081101561102857600080fd5b505190508015611086578b6001600160a01b031663f5571beb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561106d57600080fd5b505af1158015611081573d6000803e3d6000fd5b505050505b603a54604080516370a0823160e01b8152306004820152905187926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156110d057600080fd5b505afa1580156110e4573d6000803e3d6000fd5b505050506040513d60208110156110fa57600080fd5b5051101561114f576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768207355534420696e20636f6e74726163742e00000000604482015290519081900360640190fd5b603a546040805163a9059cbb60e01b81523360048201526024810188905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b1580156111a357600080fd5b505af11580156111b7573d6000803e3d6000fd5b505050506040513d60208110156111cd57600080fd5b50506001600160a01b038c166000908152604160205260409020546111f8908663ffffffff613d6116565b6001600160a01b038d1660009081526041602052604090208190558110611237576001600160a01b038c1660009081526041602052604081205561127a565b6001600160a01b038c16600090815260416020526040902054611260908263ffffffff61386016565b6001600160a01b038d166000908152604160205260409020555b7f1d6ff70c632edb1e6aba7fbc0148db68c8392e30f9dfaadae2543a2543757cf6338d8d8d89603a60009054906101000a90046001600160a01b03168860405180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b031681526020018660018111156112f757fe5b60ff1681526020810195909552506040808501939093526001600160a01b039182166060850152166080830152519081900360a0019350915050a1505050505050600454811461138e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b505050505050565b603b546001600160a01b031681565b6001816001600160a01b031663b1c9fe6e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e057600080fd5b505afa1580156113f4573d6000803e3d6000fd5b505050506040513d602081101561140a57600080fd5b5051600281111561141757fe5b14611469576040805162461bcd60e51b815260206004820152601f60248201527f4d61726b6574206973206e6f7420696e204d6174757269747920706861736500604482015290519081900360640190fd5b603b546040805163e62b888960e01b81526001600160a01b0384811660048301529151919092169163e62b8889916024808301926020929190829003018186803b1580156114b657600080fd5b505afa1580156114ca573d6000803e3d6000fd5b505050506040513d60208110156114e057600080fd5b5051611524576040805162461bcd60e51b815260206004820152600e60248201526d155b9adb9bdddb881b585c9ad95d60921b604482015290519081900360640190fd5b61152d81612f25565b611577576040805162461bcd60e51b81526020600482015260166024820152754e6f206f7074696f6e7320746f20657865726369736560501b604482015290519081900360640190fd5b806001600160a01b031663851492586040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156115b257600080fd5b505af11580156115c6573d6000803e3d6000fd5b505050506040513d60208110156115dc57600080fd5b505050565b6001546001600160a01b031681565b603b5460408051633761c52760e11b81526001600160a01b03848116600483015291516000939290921691636ec38a4e91602480820192602092909190829003018186803b15801561164157600080fd5b505afa158015611655573d6000803e3d6000fd5b505050506040513d602081101561166b57600080fd5b5051156117935760008290506000806000836001600160a01b03166398508ecd6040518163ffffffff1660e01b815260040160606040518083038186803b1580156116b557600080fd5b505afa1580156116c9573d6000803e3d6000fd5b505050506040513d60608110156116df57600080fd5b5080516020808301516040938401516000848152603f90935293909120549195509350909150611716576000945050505050611797565b600080856001600160a01b0316639e3b34bf6040518163ffffffff1660e01b8152600401604080518083038186803b15801561175157600080fd5b505afa158015611765573d6000803e3d6000fd5b505050506040513d604081101561177b57600080fd5b50516040544290910311965061179795505050505050565b5060005b919050565b60035460ff1681565b6117ad613980565b6000828152603f6020908152604091829020839055815184815290810183905281517f715e0a52c0b74c77d2d2012a363ac95b494302ad2abb78ac7406ec93451f1adb929181900390910190a15050565b603d5481565b6038546001600160a01b031681565b600061181e836115f0565b15611a21576000839050600080826001600160a01b0316639e3b34bf6040518163ffffffff1660e01b8152600401604080518083038186803b15801561186357600080fd5b505afa158015611877573d6000803e3d6000fd5b505050506040513d604081101561188d57600080fd5b508051602090910151909250905042820360006118bf6201518061087784670de0b6b3a764000063ffffffff6138bd16565b90506000856001600160a01b031663668aa8246040518163ffffffff1660e01b815260040160206040518083038186803b1580156118fc57600080fd5b505afa158015611910573d6000803e3d6000fd5b505050506040513d602081101561192657600080fd5b5051604080516398508ecd60e01b81529051919250600091829182916001600160a01b038b16916398508ecd916004808301926060929190829003018186803b15801561197257600080fd5b505afa158015611986573d6000803e3d6000fd5b505050506040513d606081101561199c57600080fd5b5080516020820151604090920151909450909250905060008b60018111156119c057fe5b14156119fa576119ea6064610877868589603f60008a815260200190815260200160002054612460565b9950505050505050505050611a25565b6119ea610855606461087787868a603f60008b815260200190815260200160002054612460565b5060005b92915050565b611a33613980565b603980546001600160a01b0383166001600160a01b0319909116811790915560408051918252517ff724a45d041687842411f2b977ef22ab8f43c8f1104f4592b42a00f9b34a643d9181900360200190a150565b6039546001600160a01b031681565b611a9e613980565b6001600160a01b03811615611b3257603a546040805163095ea7b360e01b81526001600160a01b038481166004830152600060248301819052925193169263095ea7b392604480840193602093929083900390910190829087803b158015611b0557600080fd5b505af1158015611b19573d6000803e3d6000fd5b505050506040513d6020811015611b2f57600080fd5b50505b603b80546001600160a01b0319166001600160a01b038381169190911791829055603a546040805163095ea7b360e01b8152938316600485015260001960248501525191169163095ea7b39160448083019260209291908290030181600087803b158015611b9f57600080fd5b505af1158015611bb3573d6000803e3d6000fd5b505050506040513d6020811015611bc957600080fd5b5050604080516001600160a01b038316815290517fcea2aea50ed8fa12062e9ad0a16093152af67e7c46a0d706227f8e722e2793ca9181900360200190a150565b6001546001600160a01b03163314611c535760405162461bcd60e51b81526004018080602001828103825260358152602001806140e16035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b611cce613980565b6040818155805182815290517fdc469b5583fa9b7ebd3245e1665334cd758c4bef4c5a132c62baca85effacfec9181900360200190a150565b600480546001019081905560035460ff1615611d545760405162461bcd60e51b815260040180806020018281038252603c8152602001806141bd603c913960400191505060405180910390fd5b611d5d866115f0565b611dae576040805162461bcd60e51b815260206004820152601e60248201527f4d61726b6574206973206e6f7420696e2054726164696e672070686173650000604482015290519081900360640190fd5b6000611dba878761320a565b9050600081118015611dcc5750808511155b611e15576040805162461bcd60e51b81526020600482015260156024820152742737ba1032b737bab3b4103634b8bab4b234ba3c9760591b604482015290519081900360640190fd5b6000611e22888888610b14565b603a54604080516370a0823160e01b8152336004820152905192935083926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015611e7257600080fd5b505afa158015611e86573d6000803e3d6000fd5b505050506040513d6020811015611e9c57600080fd5b50511015611ef1576040805162461bcd60e51b815260206004820152601a60248201527f596f7520646f6e74206861766520656e6f75676820735553442e000000000000604482015290519081900360640190fd5b603a5460408051636eb1769f60e11b8152336004820152306024820152905183926001600160a01b03169163dd62ed3e916044808301926020929190829003018186803b158015611f4157600080fd5b505afa158015611f55573d6000803e3d6000fd5b505050506040513d6020811015611f6b57600080fd5b50511015611fb0576040805162461bcd60e51b815260206004820152600d60248201526c27379030b63637bbb0b731b29760991b604482015290519081900360640190fd5b611fc8670de0b6b3a76400008563ffffffff613d6116565b611fe48661087784670de0b6b3a764000063ffffffff6138bd16565b111561202b576040805162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604482015290519081900360640190fd5b603a54604080516323b872dd60e01b81523360048201523060248201526044810184905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b15801561208557600080fd5b505af1158015612099573d6000803e3d6000fd5b505050506040513d60208110156120af57600080fd5b50600090506120bf898989613dbb565b9050801561223157603a54604080516370a0823160e01b8152306004820152905183926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561211157600080fd5b505afa158015612125573d6000803e3d6000fd5b505050506040513d602081101561213b57600080fd5b50511015612190576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768207355534420696e20636f6e74726163742e00000000604482015290519081900360640190fd5b886001600160a01b031663a0712d68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156121d657600080fd5b505af11580156121ea573d6000803e3d6000fd5b5050506001600160a01b038a1660009081526041602052604090205461221791508263ffffffff613d6116565b6001600160a01b038a166000908152604160205260409020555b6000808a6001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b15801561226c57600080fd5b505afa158015612280573d6000803e3d6000fd5b505050506040513d604081101561229657600080fd5b50805160209091015190925090506000808b60018111156122b357fe5b146122be57816122c0565b825b6040805163a9059cbb60e01b8152336004820152602481018d905290519192506001600160a01b0383169163a9059cbb916044808201926020929091908290030181600087803b15801561231357600080fd5b505af1158015612327573d6000803e3d6000fd5b505050506040513d602081101561233d57600080fd5b50506001600160a01b038c16600090815260416020526040902054851061237c576001600160a01b038c166000908152604160205260408120556123bf565b6001600160a01b038c166000908152604160205260409020546123a5908663ffffffff61386016565b6001600160a01b038d166000908152604160205260409020555b7ff3bfbc0822d1ed667a2b298e71e0304f2c1f4685398189d7c39e412f733150f4338d8d8d89603a60009054906101000a90046001600160a01b03168760405180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b031681526020018660018111156112f757fe5b6000546001600160a01b031681565b60025481565b603a546001600160a01b031681565b6000806124a5633b9aca006108776124886124838861016d63ffffffff61391616565b613dee565b61249987606463ffffffff61391616565b9063ffffffff6138bd16565b9050858510156000816124d3576124ce876108778a670de0b6b3a764000063ffffffff6138bd16565b6124ef565b6124ef8861087789670de0b6b3a764000063ffffffff6138bd16565b603854604080516344f7787f60e01b81526004810184905260636024820152905192935060009261259192879261087792670de0b6b3a7640000926001600160a01b0316916344f7787f916044808301926020929190829003018186803b15801561255957600080fd5b505afa15801561256d573d6000803e3d6000fd5b505050506040513d602081101561258357600080fd5b50519063ffffffff6138bd16565b905060006125cd6125b5610b6962989680610877866223588363ffffffff6138bd16565b610877670de0b6b3a76400008063ffffffff6138bd16565b905060006125f0670de0b6b3a7640000610877600281878063ffffffff6138bd16565b9050600061260b62989680610877623cdfaf61249986613e3f565b60385460408051632e4c697f60e01b815260048101879052674563918244f400006024820152905192935060009261267a92620f4240926108779262144c62926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b60385460408051632e4c697f60e01b815260048101889052673782dace9d900000602482015290519293506000926126e992620f42409261087792621bca48926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b60385460408051632e4c697f60e01b8152600481018990526729a2241af62c00006024820152905192935060009261275892620f42409261087792621b2ee6926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b60385460408051632e4c697f60e01b8152600481018a9052671bc16d674ec80000602482015290519293506000926127c792620f42409261087792620570ba926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b905060006127e5629896806108778a6230bbd763ffffffff6138bd16565b9050600061281b8361280f8781866128038c8b63ffffffff613d6116565b9063ffffffff613d6116565b9063ffffffff61386016565b9050600061283e610855670de0b6b3a76400006108778b8663ffffffff6138bd16565b9050600061286f61285683606463ffffffff6138bd16565b61280f670de0b6b3a7640000606463ffffffff6138bd16565b90508d1561288d579e50610aaa9d5050505050505050505050505050565b6128aa8161280f670de0b6b3a7640000606463ffffffff6138bd16565b9f50505050505050505050505050505050949350505050565b6128cb613980565b603a54604080516370a0823160e01b815230600482015290516001600160a01b039092169163a9059cbb91849184916370a08231916024808301926020929190829003018186803b15801561291f57600080fd5b505afa158015612933573d6000803e3d6000fd5b505050506040513d602081101561294957600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091525160448083019260209291908290030181600087803b1580156115b257600080fd5b60055462010000900460ff16806129b457506129b4613e68565b806129c75750600554610100900460ff16155b612a025760405162461bcd60e51b815260040180806020018281038252602e81526020018061418f602e913960400191505060405180910390fd5b60055462010000900460ff16158015612a32576005805461ff001962ff0000199091166201000017166101001790555b612a3b8961089b565b612a436131a7565b603980546001600160a01b03808b166001600160a01b031992831617909255603a80548a8416908316179055603c8890556038805492881692909116919091179055603d849055603e83905560408290558015612aa7576005805462ff0000191690555b505050505050505050565b612aba613980565b603e8190556040805182815290517f4af6d03c4624e0a6b868b8f6453e047f23f3ea15e9d08c938bd4c445d7ef19b39181900360200190a150565b6000612b01848461320a565b821115612b1057506000610894565b610aaa8484846139cb565b6000612b26836115f0565b15611a21576000612b378484611813565b905067016345785d8a000081111580612b585750670c7d713b49da00008110155b15612b67576000915050611a25565b6000612ba2670de0b6b3a7640000610877612b95603e54670de0b6b3a764000061386090919063ffffffff16565b859063ffffffff6138bd16565b905060008111612bf9576040805162461bcd60e51b815260206004820152601a60248201527f646976206279207a65726f2073656c6c5f6d61785f7072696365000000000000604482015290519081900360640190fd5b600080866001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015612c3457600080fd5b505afa158015612c48573d6000803e3d6000fd5b505050506040513d6040811015612c5e57600080fd5b5080516020909101519092509050600080876001811115612c7b57fe5b14612cf757604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015612cc657600080fd5b505afa158015612cda573d6000803e3d6000fd5b505050506040513d6020811015612cf057600080fd5b5051612d6a565b604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b158015612d3d57600080fd5b505afa158015612d51573d6000803e3d6000fd5b505050506040513d6020811015612d6757600080fd5b50515b90506000612d8a670de0b6b3a7640000610877848863ffffffff6138bd16565b6001600160a01b038a16600090815260416020526040812054603c549293509091612dc491849161280f919082908863ffffffff613d6116565b9050612de683612803670de0b6b3a7640000612499858b63ffffffff61391616565b975050505050505050611a25565b612dfc613980565b6001600160a01b038116612e49576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b600154600160a81b900460ff1615612e9e576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b604482015290519081900360640190fd5b600080546001600160a01b038084166001600160a01b03199092168217928390556001805460ff60a81b1916600160a81b17905560408051939091168352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b60416020526000908152604090205481565b603b546040805163e62b888960e01b81526001600160a01b0384811660048301529151600093929092169163e62b888991602480820192602092909190829003018186803b158015612f7657600080fd5b505afa158015612f8a573d6000803e3d6000fd5b505050506040513d6020811015612fa057600080fd5b5051801561301d57506001826001600160a01b031663b1c9fe6e6040518163ffffffff1660e01b815260040160206040518083038186803b158015612fe457600080fd5b505afa158015612ff8573d6000803e3d6000fd5b505050506040513d602081101561300e57600080fd5b5051600281111561301b57fe5b145b1561179357600080836001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b15801561305d57600080fd5b505afa158015613071573d6000803e3d6000fd5b505050506040513d604081101561308757600080fd5b508051602091820151604080516370a0823160e01b815230600482015290519295509093506000926001600160a01b038616926370a08231926024808201939291829003018186803b1580156130dc57600080fd5b505afa1580156130f0573d6000803e3d6000fd5b505050506040513d602081101561310657600080fd5b505111806131875750604080516370a0823160e01b815230600482015290516000916001600160a01b038416916370a0823191602480820192602092909190829003018186803b15801561315957600080fd5b505afa15801561316d573d6000803e3d6000fd5b505050506040513d602081101561318357600080fd5b5051115b1561319757600192505050611797565b5050506000919050565b60405481565b60055460ff16156131f5576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b6005805460ff19166001908117909155600455565b6000613215836115f0565b15611a215760006132268484611813565b905067016345785d8a0000811115806132475750670c7d713b49da00008110155b15613256576000915050611a25565b60006132628585613e6e565b90506000613292670de0b6b3a7640000610877610883603e54670de0b6b3a7640000613d6190919063ffffffff16565b90506132b3670de0b6b3a7640000662386f26fc1000063ffffffff61386016565b811015806132c85750662386f26fc100008111155b156132d95760009350505050611a25565b60006132f3670de0b6b3a76400008363ffffffff61386016565b90506000613313670de0b6b3a7640000610877868663ffffffff6138bd16565b6001600160a01b038916600090815260416020526040902054603c5491925090613343908363ffffffff613d6116565b1161335657600095505050505050611a25565b6001600160a01b038816600090815260416020526040812054603c54613387919061280f908563ffffffff613d6116565b90506133b56133a8670de0b6b3a7640000612499848763ffffffff61391616565b869063ffffffff613d6116565b9650505050505050611a25565b603f6020526000908152604090205481565b6133dc613980565b603c8190556040805182815290517fcc72495e91bfc45ec11465a752fc2866b8a5ef8960b0925774ede927ee7cbdbe9181900360200190a150565b61341f613980565b603d8190556040805182815290517f1e6a338a58debcc786781a079c4459466b102ad0156cc84f51d25ef7dd8cb9b09181900360200190a150565b603c5481565b6000806000856001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b15801561349d57600080fd5b505afa1580156134b1573d6000803e3d6000fd5b505050506040513d60408110156134c757600080fd5b50805160209091015190925090506000808660018111156134e457fe5b1461356057604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561352f57600080fd5b505afa158015613543573d6000803e3d6000fd5b505050506040513d602081101561355957600080fd5b50516135d3565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156135a657600080fd5b505afa1580156135ba573d6000803e3d6000fd5b505050506040513d60208110156135d057600080fd5b50515b90506000808760018111156135e457fe5b1461366057604080516370a0823160e01b815230600482015290516001600160a01b038616916370a08231916024808301926020929190829003018186803b15801561362f57600080fd5b505afa158015613643573d6000803e3d6000fd5b505050506040513d602081101561365957600080fd5b50516136d3565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156136a657600080fd5b505afa1580156136ba573d6000803e3d6000fd5b505050506040513d60208110156136d057600080fd5b50515b905060006136e7838863ffffffff613d6116565b90506000613705670de0b6b3a76400006108778a6124998e8e613feb565b90508282101561371f57603d549650505050505050610894565b600061372b8b8b611813565b9050600061373f848663ffffffff61386016565b90506000821161378e576040805162461bcd60e51b8152602060048201526015602482015274646976206279207a65726f2062617365507269636560581b604482015290519081900360640190fd5b60006137b183610877670de0b6b3a7640000603c546138bd90919063ffffffff16565b905060008111613808576040805162461bcd60e51b815260206004820152601b60248201527f646976206279207a65726f206d6178506f737369626c65536b65770000000000604482015290519081900360640190fd5b613850613841670de0b6b3a764000061087761382c8582888563ffffffff6138bd16565b603d54603e546124999163ffffffff61386016565b603d549063ffffffff613d6116565b9950505050505050505050610894565b6000828211156138b7576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826138cc57506000611a25565b828202828482816138d957fe5b04146108945760405162461bcd60e51b815260040180806020018281038252602181526020018061416e6021913960400191505060405180910390fd5b600080821161396c576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161397757fe5b04949350505050565b6000546001600160a01b031633146139c95760405162461bcd60e51b815260040180806020018281038252602f81526020018061413f602f913960400191505060405180910390fd5b565b6000806000856001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015613a0857600080fd5b505afa158015613a1c573d6000803e3d6000fd5b505050506040513d6040811015613a3257600080fd5b5080516020909101519092509050600080866001811115613a4f57fe5b14613acb57604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b158015613a9a57600080fd5b505afa158015613aae573d6000803e3d6000fd5b505050506040513d6020811015613ac457600080fd5b5051613b3e565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015613b1157600080fd5b505afa158015613b25573d6000803e3d6000fd5b505050506040513d6020811015613b3b57600080fd5b50515b9050600080876001811115613b4f57fe5b14613bcb57604080516370a0823160e01b815230600482015290516001600160a01b038616916370a08231916024808301926020929190829003018186803b158015613b9a57600080fd5b505afa158015613bae573d6000803e3d6000fd5b505050506040513d6020811015613bc457600080fd5b5051613c3e565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015613c1157600080fd5b505afa158015613c25573d6000803e3d6000fd5b505050506040513d6020811015613c3b57600080fd5b50515b90506000868311613c50576000613c60565b613c60838863ffffffff61386016565b90506000878411613c9057613c8b613c7e898663ffffffff61386016565b849063ffffffff613d6116565b613c92565b825b90506000613cb0670de0b6b3a76400006108778b6124998f8f614023565b9050818310613cca57603d54975050505050505050610894565b6000613cf18c828d6001811115613cdd57fe5b14613ce9576000613cec565b60015b611813565b90506000613d05848663ffffffff61386016565b90506000613d2a83610877670de0b6b3a7640000603c546138bd90919063ffffffff16565b9050613d50613841670de0b6b3a764000061087761382c8582888563ffffffff6138bd16565b9a5050505050505050505050610894565b600082820183811015610894576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600080613dc88585613e6e565b90506000915082811015613de657610890838263ffffffff61386016565b509392505050565b60006003821115613e31575080600160028204015b81811015613e2b57809150600281828581613e1a57fe5b040181613e2357fe5b049050613e03565b50611797565b811561179757506001919050565b6000613e4a82614051565b6ec097ce7bc90715b34b9f100000000081613e6157fe5b0492915050565b303b1590565b6000806000846001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015613eab57600080fd5b505afa158015613ebf573d6000803e3d6000fd5b505050506040513d6040811015613ed557600080fd5b5080516020909101519092509050600080856001811115613ef257fe5b14613f6e57604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b158015613f3d57600080fd5b505afa158015613f51573d6000803e3d6000fd5b505050506040513d6020811015613f6757600080fd5b5051613fe1565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015613fb457600080fd5b505afa158015613fc8573d6000803e3d6000fd5b505050506040513d6020811015613fde57600080fd5b50515b9695505050505050565b6000610894670de0b6b3a7640000610877614019603d54670de0b6b3a764000061386090919063ffffffff16565b6124998787611813565b6000610894670de0b6b3a7640000610877614019603d54670de0b6b3a7640000613d6190919063ffffffff16565b60385460408051632e4c697f60e01b81526725b94542080c8000600482018190526024820185905291516000936001600160a01b031691632e4c697f916044808301926020929190829003018186803b1580156140ad57600080fd5b505afa1580156140c1573d6000803e3d6000fd5b505050506040513d60208110156140d757600080fd5b5051939250505056fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e657273686970416c726561647920696e697469616c697a65642c20757365206e6f6d696e6174654e65774f776e65724f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a65645468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e747261637420697320706175736564a265627a7a723158201983215b1d3a52f153b1a33e58e0d676fb473dad00152b998b94ce1ec637121964736f6c63430005100032

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102695760003560e01c806379ba509711610151578063c2783f92116100c3578063ebc7977211610087578063ebc797721461076a578063efc1525114610772578063f502b003146107a1578063f598df82146107be578063f85de9fa146107db578063fb91d41c146107f857610269565b8063c2783f92146106c1578063c3b83f5f146106f0578063c4dc27d714610716578063ca1d578e1461073c578063df8974d01461076257610269565b80639324cac7116101155780639324cac7146105bb578063a8cd06e8146105c3578063a996798c146105f2578063ad18f0da14610618578063bef648db1461066f578063bf46c0b41461068c57610269565b806379ba509714610545578063851702091461054d5780638875eb841461056a5780638da5cb5b146105ab57806391b4ded9146105b357610269565b806351b9181f116101ea5780636aaa81b6116101ae5780636aaa81b6146104b25780636cfa636e146104ba5780636ed033f8146104c2578063724e78da146104f1578063741bef1a1461051757806375cdc2281461051f57610269565b806351b9181f1461041f57806353a47bb7146104455780635727a0f31461044d5780635c975abb146104875780635ef85b261461048f57610269565b806321ef44c61161023157806321ef44c614610357578063270e13ef1461037d578063316425c3146103b25780633ce1108d146103ba578063481c6a75146103fb57610269565b80630f13aae81461026e57806313af4035146102b55780631627540c146102dd57806316c38b3c146103035780631c37d04b14610322575b600080fd5b6102a36004803603606081101561028457600080fd5b506001600160a01b038135169060ff6020820135169060400135610800565b60408051918252519081900360200190f35b6102db600480360360208110156102cb57600080fd5b50356001600160a01b031661089b565b005b6102db600480360360208110156102f357600080fd5b50356001600160a01b03166109ae565b6102db6004803603602081101561031957600080fd5b50351515610a0a565b6102a36004803603606081101561033857600080fd5b506001600160a01b038135169060ff6020820135169060400135610a84565b6102db6004803603602081101561036d57600080fd5b50356001600160a01b0316610ab2565b6102a36004803603606081101561039357600080fd5b506001600160a01b038135169060ff6020820135169060400135610b14565b6102a3610b7e565b6102db600480360360a08110156103d057600080fd5b506001600160a01b038135169060ff6020820135169060408101359060608101359060800135610b84565b610403611396565b604080516001600160a01b039092168252519081900360200190f35b6102db6004803603602081101561043557600080fd5b50356001600160a01b03166113a5565b6104036115e1565b6104736004803603602081101561046357600080fd5b50356001600160a01b03166115f0565b604080519115158252519081900360200190f35b61047361179c565b6102db600480360360408110156104a557600080fd5b50803590602001356117a5565b6102a36117fe565b610403611804565b6102a3600480360360408110156104d857600080fd5b5080356001600160a01b0316906020013560ff16611813565b6102db6004803603602081101561050757600080fd5b50356001600160a01b0316611a2b565b610403611a87565b6102db6004803603602081101561053557600080fd5b50356001600160a01b0316611a96565b6102db611c0a565b6102db6004803603602081101561056357600080fd5b5035611cc6565b6102db600480360360a081101561058057600080fd5b506001600160a01b038135169060ff6020820135169060408101359060608101359060800135611d07565b61040361243c565b6102a361244b565b610403612451565b6102a3600480360360808110156105d957600080fd5b5080359060208101359060408101359060600135612460565b6102db6004803603602081101561060857600080fd5b50356001600160a01b03166128c3565b6102db600480360361010081101561062f57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135916080820135169060a08101359060c08101359060e0013561299a565b6102db6004803603602081101561068557600080fd5b5035612ab2565b6102a3600480360360608110156106a257600080fd5b506001600160a01b038135169060ff6020820135169060400135612af5565b6102a3600480360360408110156106d757600080fd5b5080356001600160a01b0316906020013560ff16612b1b565b6102db6004803603602081101561070657600080fd5b50356001600160a01b0316612df4565b6102a36004803603602081101561072c57600080fd5b50356001600160a01b0316612f13565b6104736004803603602081101561075257600080fd5b50356001600160a01b0316612f25565b6102a36131a1565b6102db6131a7565b6102a36004803603604081101561078857600080fd5b5080356001600160a01b0316906020013560ff1661320a565b6102a3600480360360208110156107b757600080fd5b50356133c2565b6102db600480360360208110156107d457600080fd5b50356133d4565b6102db600480360360208110156107f157600080fd5b5035613417565b6102a361345a565b600061080c8484612b1b565b82111561081b57506000610894565b60006108278585611813565b9050610890670de0b6b3a7640000610877610883670de0b6b3a764000061087761086a6108558c8c8c613460565b670de0b6b3a76400009063ffffffff61386016565b879063ffffffff6138bd16565b9063ffffffff61391616565b869063ffffffff6138bd16565b9150505b9392505050565b6001600160a01b0381166108f6576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600154600160a01b900460ff161561093f5760405162461bcd60e51b81526004018080602001828103825260298152602001806141166029913960400191505060405180910390fd5b6001805460ff60a01b1916600160a01b179055600080546001600160a01b0383166001600160a01b03199091168117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b6109b6613980565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b610a12613980565b60035460ff1615158115151415610a2857610a81565b6003805460ff1916821515179081905560ff1615610a4557426002555b6003546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b6000610a908484612b1b565b821115610a9f57506000610894565b610aaa848484613460565b949350505050565b610aba613980565b603a80546001600160a01b0319166001600160a01b03838116919091179182905560408051929091168252517f74a8764fc8d62d2d844c8c54426bd94ad034e0e92abdf5280ff75e2cbd678fb6916020908290030190a150565b6000610b20848461320a565b821115610b2f57506000610894565b6000610b3b8585611813565b9050610890670de0b6b3a7640000610877610883670de0b6b3a764000061087761086a610b698c8c8c6139cb565b670de0b6b3a76400009063ffffffff613d6116565b603e5481565b600480546001019081905560035460ff1615610bd15760405162461bcd60e51b815260040180806020018281038252603c8152602001806141bd603c913960400191505060405180910390fd5b610bda866115f0565b610c2b576040805162461bcd60e51b815260206004820152601e60248201527f4d61726b6574206973206e6f7420696e2054726164696e672070686173650000604482015290519081900360640190fd5b6000610c378787612b1b565b9050600081118015610c495750808511155b610c92576040805162461bcd60e51b81526020600482015260156024820152742737ba1032b737bab3b4103634b8bab4b234ba3c9760591b604482015290519081900360640190fd5b6000610c9f888888610800565b9050610cb9670de0b6b3a76400008563ffffffff613d6116565b610cd58261087788670de0b6b3a764000063ffffffff6138bd16565b1115610d1c576040805162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604482015290519081900360640190fd5b600080896001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015610d5757600080fd5b505afa158015610d6b573d6000803e3d6000fd5b505050506040513d6040811015610d8157600080fd5b50805160209091015190925090506000808a6001811115610d9e57fe5b14610da95781610dab565b825b604080516370a0823160e01b815233600482015290519192508a916001600160a01b038416916370a08231916024808301926020929190829003018186803b158015610df657600080fd5b505afa158015610e0a573d6000803e3d6000fd5b505050506040513d6020811015610e2057600080fd5b50511015610e75576040805162461bcd60e51b815260206004820152601d60248201527f596f7520646f6e74206861766520656e6f756768206f7074696f6e732e000000604482015290519081900360640190fd5b60408051636eb1769f60e11b815233600482015230602482015290518a916001600160a01b0384169163dd62ed3e91604480820192602092909190829003018186803b158015610ec457600080fd5b505afa158015610ed8573d6000803e3d6000fd5b505050506040513d6020811015610eee57600080fd5b50511015610f33576040805162461bcd60e51b815260206004820152600d60248201526c27379030b63637bbb0b731b29760991b604482015290519081900360640190fd5b604080516323b872dd60e01b8152336004820152306024820152604481018b905290516001600160a01b038316916323b872dd9160648083019260209291908290030181600087803b158015610f8857600080fd5b505af1158015610f9c573d6000803e3d6000fd5b505050506040513d6020811015610fb257600080fd5b5050604080516314edbee160e31b815230600482015290516000916001600160a01b038e169163a76df70891602480820192602092909190829003018186803b158015610ffe57600080fd5b505afa158015611012573d6000803e3d6000fd5b505050506040513d602081101561102857600080fd5b505190508015611086578b6001600160a01b031663f5571beb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561106d57600080fd5b505af1158015611081573d6000803e3d6000fd5b505050505b603a54604080516370a0823160e01b8152306004820152905187926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156110d057600080fd5b505afa1580156110e4573d6000803e3d6000fd5b505050506040513d60208110156110fa57600080fd5b5051101561114f576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768207355534420696e20636f6e74726163742e00000000604482015290519081900360640190fd5b603a546040805163a9059cbb60e01b81523360048201526024810188905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b1580156111a357600080fd5b505af11580156111b7573d6000803e3d6000fd5b505050506040513d60208110156111cd57600080fd5b50506001600160a01b038c166000908152604160205260409020546111f8908663ffffffff613d6116565b6001600160a01b038d1660009081526041602052604090208190558110611237576001600160a01b038c1660009081526041602052604081205561127a565b6001600160a01b038c16600090815260416020526040902054611260908263ffffffff61386016565b6001600160a01b038d166000908152604160205260409020555b7f1d6ff70c632edb1e6aba7fbc0148db68c8392e30f9dfaadae2543a2543757cf6338d8d8d89603a60009054906101000a90046001600160a01b03168860405180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b031681526020018660018111156112f757fe5b60ff1681526020810195909552506040808501939093526001600160a01b039182166060850152166080830152519081900360a0019350915050a1505050505050600454811461138e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b505050505050565b603b546001600160a01b031681565b6001816001600160a01b031663b1c9fe6e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e057600080fd5b505afa1580156113f4573d6000803e3d6000fd5b505050506040513d602081101561140a57600080fd5b5051600281111561141757fe5b14611469576040805162461bcd60e51b815260206004820152601f60248201527f4d61726b6574206973206e6f7420696e204d6174757269747920706861736500604482015290519081900360640190fd5b603b546040805163e62b888960e01b81526001600160a01b0384811660048301529151919092169163e62b8889916024808301926020929190829003018186803b1580156114b657600080fd5b505afa1580156114ca573d6000803e3d6000fd5b505050506040513d60208110156114e057600080fd5b5051611524576040805162461bcd60e51b815260206004820152600e60248201526d155b9adb9bdddb881b585c9ad95d60921b604482015290519081900360640190fd5b61152d81612f25565b611577576040805162461bcd60e51b81526020600482015260166024820152754e6f206f7074696f6e7320746f20657865726369736560501b604482015290519081900360640190fd5b806001600160a01b031663851492586040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156115b257600080fd5b505af11580156115c6573d6000803e3d6000fd5b505050506040513d60208110156115dc57600080fd5b505050565b6001546001600160a01b031681565b603b5460408051633761c52760e11b81526001600160a01b03848116600483015291516000939290921691636ec38a4e91602480820192602092909190829003018186803b15801561164157600080fd5b505afa158015611655573d6000803e3d6000fd5b505050506040513d602081101561166b57600080fd5b5051156117935760008290506000806000836001600160a01b03166398508ecd6040518163ffffffff1660e01b815260040160606040518083038186803b1580156116b557600080fd5b505afa1580156116c9573d6000803e3d6000fd5b505050506040513d60608110156116df57600080fd5b5080516020808301516040938401516000848152603f90935293909120549195509350909150611716576000945050505050611797565b600080856001600160a01b0316639e3b34bf6040518163ffffffff1660e01b8152600401604080518083038186803b15801561175157600080fd5b505afa158015611765573d6000803e3d6000fd5b505050506040513d604081101561177b57600080fd5b50516040544290910311965061179795505050505050565b5060005b919050565b60035460ff1681565b6117ad613980565b6000828152603f6020908152604091829020839055815184815290810183905281517f715e0a52c0b74c77d2d2012a363ac95b494302ad2abb78ac7406ec93451f1adb929181900390910190a15050565b603d5481565b6038546001600160a01b031681565b600061181e836115f0565b15611a21576000839050600080826001600160a01b0316639e3b34bf6040518163ffffffff1660e01b8152600401604080518083038186803b15801561186357600080fd5b505afa158015611877573d6000803e3d6000fd5b505050506040513d604081101561188d57600080fd5b508051602090910151909250905042820360006118bf6201518061087784670de0b6b3a764000063ffffffff6138bd16565b90506000856001600160a01b031663668aa8246040518163ffffffff1660e01b815260040160206040518083038186803b1580156118fc57600080fd5b505afa158015611910573d6000803e3d6000fd5b505050506040513d602081101561192657600080fd5b5051604080516398508ecd60e01b81529051919250600091829182916001600160a01b038b16916398508ecd916004808301926060929190829003018186803b15801561197257600080fd5b505afa158015611986573d6000803e3d6000fd5b505050506040513d606081101561199c57600080fd5b5080516020820151604090920151909450909250905060008b60018111156119c057fe5b14156119fa576119ea6064610877868589603f60008a815260200190815260200160002054612460565b9950505050505050505050611a25565b6119ea610855606461087787868a603f60008b815260200190815260200160002054612460565b5060005b92915050565b611a33613980565b603980546001600160a01b0383166001600160a01b0319909116811790915560408051918252517ff724a45d041687842411f2b977ef22ab8f43c8f1104f4592b42a00f9b34a643d9181900360200190a150565b6039546001600160a01b031681565b611a9e613980565b6001600160a01b03811615611b3257603a546040805163095ea7b360e01b81526001600160a01b038481166004830152600060248301819052925193169263095ea7b392604480840193602093929083900390910190829087803b158015611b0557600080fd5b505af1158015611b19573d6000803e3d6000fd5b505050506040513d6020811015611b2f57600080fd5b50505b603b80546001600160a01b0319166001600160a01b038381169190911791829055603a546040805163095ea7b360e01b8152938316600485015260001960248501525191169163095ea7b39160448083019260209291908290030181600087803b158015611b9f57600080fd5b505af1158015611bb3573d6000803e3d6000fd5b505050506040513d6020811015611bc957600080fd5b5050604080516001600160a01b038316815290517fcea2aea50ed8fa12062e9ad0a16093152af67e7c46a0d706227f8e722e2793ca9181900360200190a150565b6001546001600160a01b03163314611c535760405162461bcd60e51b81526004018080602001828103825260358152602001806140e16035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b611cce613980565b6040818155805182815290517fdc469b5583fa9b7ebd3245e1665334cd758c4bef4c5a132c62baca85effacfec9181900360200190a150565b600480546001019081905560035460ff1615611d545760405162461bcd60e51b815260040180806020018281038252603c8152602001806141bd603c913960400191505060405180910390fd5b611d5d866115f0565b611dae576040805162461bcd60e51b815260206004820152601e60248201527f4d61726b6574206973206e6f7420696e2054726164696e672070686173650000604482015290519081900360640190fd5b6000611dba878761320a565b9050600081118015611dcc5750808511155b611e15576040805162461bcd60e51b81526020600482015260156024820152742737ba1032b737bab3b4103634b8bab4b234ba3c9760591b604482015290519081900360640190fd5b6000611e22888888610b14565b603a54604080516370a0823160e01b8152336004820152905192935083926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015611e7257600080fd5b505afa158015611e86573d6000803e3d6000fd5b505050506040513d6020811015611e9c57600080fd5b50511015611ef1576040805162461bcd60e51b815260206004820152601a60248201527f596f7520646f6e74206861766520656e6f75676820735553442e000000000000604482015290519081900360640190fd5b603a5460408051636eb1769f60e11b8152336004820152306024820152905183926001600160a01b03169163dd62ed3e916044808301926020929190829003018186803b158015611f4157600080fd5b505afa158015611f55573d6000803e3d6000fd5b505050506040513d6020811015611f6b57600080fd5b50511015611fb0576040805162461bcd60e51b815260206004820152600d60248201526c27379030b63637bbb0b731b29760991b604482015290519081900360640190fd5b611fc8670de0b6b3a76400008563ffffffff613d6116565b611fe48661087784670de0b6b3a764000063ffffffff6138bd16565b111561202b576040805162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604482015290519081900360640190fd5b603a54604080516323b872dd60e01b81523360048201523060248201526044810184905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b15801561208557600080fd5b505af1158015612099573d6000803e3d6000fd5b505050506040513d60208110156120af57600080fd5b50600090506120bf898989613dbb565b9050801561223157603a54604080516370a0823160e01b8152306004820152905183926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561211157600080fd5b505afa158015612125573d6000803e3d6000fd5b505050506040513d602081101561213b57600080fd5b50511015612190576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768207355534420696e20636f6e74726163742e00000000604482015290519081900360640190fd5b886001600160a01b031663a0712d68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156121d657600080fd5b505af11580156121ea573d6000803e3d6000fd5b5050506001600160a01b038a1660009081526041602052604090205461221791508263ffffffff613d6116565b6001600160a01b038a166000908152604160205260409020555b6000808a6001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b15801561226c57600080fd5b505afa158015612280573d6000803e3d6000fd5b505050506040513d604081101561229657600080fd5b50805160209091015190925090506000808b60018111156122b357fe5b146122be57816122c0565b825b6040805163a9059cbb60e01b8152336004820152602481018d905290519192506001600160a01b0383169163a9059cbb916044808201926020929091908290030181600087803b15801561231357600080fd5b505af1158015612327573d6000803e3d6000fd5b505050506040513d602081101561233d57600080fd5b50506001600160a01b038c16600090815260416020526040902054851061237c576001600160a01b038c166000908152604160205260408120556123bf565b6001600160a01b038c166000908152604160205260409020546123a5908663ffffffff61386016565b6001600160a01b038d166000908152604160205260409020555b7ff3bfbc0822d1ed667a2b298e71e0304f2c1f4685398189d7c39e412f733150f4338d8d8d89603a60009054906101000a90046001600160a01b03168760405180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b031681526020018660018111156112f757fe5b6000546001600160a01b031681565b60025481565b603a546001600160a01b031681565b6000806124a5633b9aca006108776124886124838861016d63ffffffff61391616565b613dee565b61249987606463ffffffff61391616565b9063ffffffff6138bd16565b9050858510156000816124d3576124ce876108778a670de0b6b3a764000063ffffffff6138bd16565b6124ef565b6124ef8861087789670de0b6b3a764000063ffffffff6138bd16565b603854604080516344f7787f60e01b81526004810184905260636024820152905192935060009261259192879261087792670de0b6b3a7640000926001600160a01b0316916344f7787f916044808301926020929190829003018186803b15801561255957600080fd5b505afa15801561256d573d6000803e3d6000fd5b505050506040513d602081101561258357600080fd5b50519063ffffffff6138bd16565b905060006125cd6125b5610b6962989680610877866223588363ffffffff6138bd16565b610877670de0b6b3a76400008063ffffffff6138bd16565b905060006125f0670de0b6b3a7640000610877600281878063ffffffff6138bd16565b9050600061260b62989680610877623cdfaf61249986613e3f565b60385460408051632e4c697f60e01b815260048101879052674563918244f400006024820152905192935060009261267a92620f4240926108779262144c62926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b60385460408051632e4c697f60e01b815260048101889052673782dace9d900000602482015290519293506000926126e992620f42409261087792621bca48926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b60385460408051632e4c697f60e01b8152600481018990526729a2241af62c00006024820152905192935060009261275892620f42409261087792621b2ee6926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b60385460408051632e4c697f60e01b8152600481018a9052671bc16d674ec80000602482015290519293506000926127c792620f42409261087792620570ba926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b905060006127e5629896806108778a6230bbd763ffffffff6138bd16565b9050600061281b8361280f8781866128038c8b63ffffffff613d6116565b9063ffffffff613d6116565b9063ffffffff61386016565b9050600061283e610855670de0b6b3a76400006108778b8663ffffffff6138bd16565b9050600061286f61285683606463ffffffff6138bd16565b61280f670de0b6b3a7640000606463ffffffff6138bd16565b90508d1561288d579e50610aaa9d5050505050505050505050505050565b6128aa8161280f670de0b6b3a7640000606463ffffffff6138bd16565b9f50505050505050505050505050505050949350505050565b6128cb613980565b603a54604080516370a0823160e01b815230600482015290516001600160a01b039092169163a9059cbb91849184916370a08231916024808301926020929190829003018186803b15801561291f57600080fd5b505afa158015612933573d6000803e3d6000fd5b505050506040513d602081101561294957600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091525160448083019260209291908290030181600087803b1580156115b257600080fd5b60055462010000900460ff16806129b457506129b4613e68565b806129c75750600554610100900460ff16155b612a025760405162461bcd60e51b815260040180806020018281038252602e81526020018061418f602e913960400191505060405180910390fd5b60055462010000900460ff16158015612a32576005805461ff001962ff0000199091166201000017166101001790555b612a3b8961089b565b612a436131a7565b603980546001600160a01b03808b166001600160a01b031992831617909255603a80548a8416908316179055603c8890556038805492881692909116919091179055603d849055603e83905560408290558015612aa7576005805462ff0000191690555b505050505050505050565b612aba613980565b603e8190556040805182815290517f4af6d03c4624e0a6b868b8f6453e047f23f3ea15e9d08c938bd4c445d7ef19b39181900360200190a150565b6000612b01848461320a565b821115612b1057506000610894565b610aaa8484846139cb565b6000612b26836115f0565b15611a21576000612b378484611813565b905067016345785d8a000081111580612b585750670c7d713b49da00008110155b15612b67576000915050611a25565b6000612ba2670de0b6b3a7640000610877612b95603e54670de0b6b3a764000061386090919063ffffffff16565b859063ffffffff6138bd16565b905060008111612bf9576040805162461bcd60e51b815260206004820152601a60248201527f646976206279207a65726f2073656c6c5f6d61785f7072696365000000000000604482015290519081900360640190fd5b600080866001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015612c3457600080fd5b505afa158015612c48573d6000803e3d6000fd5b505050506040513d6040811015612c5e57600080fd5b5080516020909101519092509050600080876001811115612c7b57fe5b14612cf757604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015612cc657600080fd5b505afa158015612cda573d6000803e3d6000fd5b505050506040513d6020811015612cf057600080fd5b5051612d6a565b604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b158015612d3d57600080fd5b505afa158015612d51573d6000803e3d6000fd5b505050506040513d6020811015612d6757600080fd5b50515b90506000612d8a670de0b6b3a7640000610877848863ffffffff6138bd16565b6001600160a01b038a16600090815260416020526040812054603c549293509091612dc491849161280f919082908863ffffffff613d6116565b9050612de683612803670de0b6b3a7640000612499858b63ffffffff61391616565b975050505050505050611a25565b612dfc613980565b6001600160a01b038116612e49576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b600154600160a81b900460ff1615612e9e576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b604482015290519081900360640190fd5b600080546001600160a01b038084166001600160a01b03199092168217928390556001805460ff60a81b1916600160a81b17905560408051939091168352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b60416020526000908152604090205481565b603b546040805163e62b888960e01b81526001600160a01b0384811660048301529151600093929092169163e62b888991602480820192602092909190829003018186803b158015612f7657600080fd5b505afa158015612f8a573d6000803e3d6000fd5b505050506040513d6020811015612fa057600080fd5b5051801561301d57506001826001600160a01b031663b1c9fe6e6040518163ffffffff1660e01b815260040160206040518083038186803b158015612fe457600080fd5b505afa158015612ff8573d6000803e3d6000fd5b505050506040513d602081101561300e57600080fd5b5051600281111561301b57fe5b145b1561179357600080836001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b15801561305d57600080fd5b505afa158015613071573d6000803e3d6000fd5b505050506040513d604081101561308757600080fd5b508051602091820151604080516370a0823160e01b815230600482015290519295509093506000926001600160a01b038616926370a08231926024808201939291829003018186803b1580156130dc57600080fd5b505afa1580156130f0573d6000803e3d6000fd5b505050506040513d602081101561310657600080fd5b505111806131875750604080516370a0823160e01b815230600482015290516000916001600160a01b038416916370a0823191602480820192602092909190829003018186803b15801561315957600080fd5b505afa15801561316d573d6000803e3d6000fd5b505050506040513d602081101561318357600080fd5b5051115b1561319757600192505050611797565b5050506000919050565b60405481565b60055460ff16156131f5576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b6005805460ff19166001908117909155600455565b6000613215836115f0565b15611a215760006132268484611813565b905067016345785d8a0000811115806132475750670c7d713b49da00008110155b15613256576000915050611a25565b60006132628585613e6e565b90506000613292670de0b6b3a7640000610877610883603e54670de0b6b3a7640000613d6190919063ffffffff16565b90506132b3670de0b6b3a7640000662386f26fc1000063ffffffff61386016565b811015806132c85750662386f26fc100008111155b156132d95760009350505050611a25565b60006132f3670de0b6b3a76400008363ffffffff61386016565b90506000613313670de0b6b3a7640000610877868663ffffffff6138bd16565b6001600160a01b038916600090815260416020526040902054603c5491925090613343908363ffffffff613d6116565b1161335657600095505050505050611a25565b6001600160a01b038816600090815260416020526040812054603c54613387919061280f908563ffffffff613d6116565b90506133b56133a8670de0b6b3a7640000612499848763ffffffff61391616565b869063ffffffff613d6116565b9650505050505050611a25565b603f6020526000908152604090205481565b6133dc613980565b603c8190556040805182815290517fcc72495e91bfc45ec11465a752fc2866b8a5ef8960b0925774ede927ee7cbdbe9181900360200190a150565b61341f613980565b603d8190556040805182815290517f1e6a338a58debcc786781a079c4459466b102ad0156cc84f51d25ef7dd8cb9b09181900360200190a150565b603c5481565b6000806000856001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b15801561349d57600080fd5b505afa1580156134b1573d6000803e3d6000fd5b505050506040513d60408110156134c757600080fd5b50805160209091015190925090506000808660018111156134e457fe5b1461356057604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561352f57600080fd5b505afa158015613543573d6000803e3d6000fd5b505050506040513d602081101561355957600080fd5b50516135d3565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156135a657600080fd5b505afa1580156135ba573d6000803e3d6000fd5b505050506040513d60208110156135d057600080fd5b50515b90506000808760018111156135e457fe5b1461366057604080516370a0823160e01b815230600482015290516001600160a01b038616916370a08231916024808301926020929190829003018186803b15801561362f57600080fd5b505afa158015613643573d6000803e3d6000fd5b505050506040513d602081101561365957600080fd5b50516136d3565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156136a657600080fd5b505afa1580156136ba573d6000803e3d6000fd5b505050506040513d60208110156136d057600080fd5b50515b905060006136e7838863ffffffff613d6116565b90506000613705670de0b6b3a76400006108778a6124998e8e613feb565b90508282101561371f57603d549650505050505050610894565b600061372b8b8b611813565b9050600061373f848663ffffffff61386016565b90506000821161378e576040805162461bcd60e51b8152602060048201526015602482015274646976206279207a65726f2062617365507269636560581b604482015290519081900360640190fd5b60006137b183610877670de0b6b3a7640000603c546138bd90919063ffffffff16565b905060008111613808576040805162461bcd60e51b815260206004820152601b60248201527f646976206279207a65726f206d6178506f737369626c65536b65770000000000604482015290519081900360640190fd5b613850613841670de0b6b3a764000061087761382c8582888563ffffffff6138bd16565b603d54603e546124999163ffffffff61386016565b603d549063ffffffff613d6116565b9950505050505050505050610894565b6000828211156138b7576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826138cc57506000611a25565b828202828482816138d957fe5b04146108945760405162461bcd60e51b815260040180806020018281038252602181526020018061416e6021913960400191505060405180910390fd5b600080821161396c576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161397757fe5b04949350505050565b6000546001600160a01b031633146139c95760405162461bcd60e51b815260040180806020018281038252602f81526020018061413f602f913960400191505060405180910390fd5b565b6000806000856001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015613a0857600080fd5b505afa158015613a1c573d6000803e3d6000fd5b505050506040513d6040811015613a3257600080fd5b5080516020909101519092509050600080866001811115613a4f57fe5b14613acb57604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b158015613a9a57600080fd5b505afa158015613aae573d6000803e3d6000fd5b505050506040513d6020811015613ac457600080fd5b5051613b3e565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015613b1157600080fd5b505afa158015613b25573d6000803e3d6000fd5b505050506040513d6020811015613b3b57600080fd5b50515b9050600080876001811115613b4f57fe5b14613bcb57604080516370a0823160e01b815230600482015290516001600160a01b038616916370a08231916024808301926020929190829003018186803b158015613b9a57600080fd5b505afa158015613bae573d6000803e3d6000fd5b505050506040513d6020811015613bc457600080fd5b5051613c3e565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015613c1157600080fd5b505afa158015613c25573d6000803e3d6000fd5b505050506040513d6020811015613c3b57600080fd5b50515b90506000868311613c50576000613c60565b613c60838863ffffffff61386016565b90506000878411613c9057613c8b613c7e898663ffffffff61386016565b849063ffffffff613d6116565b613c92565b825b90506000613cb0670de0b6b3a76400006108778b6124998f8f614023565b9050818310613cca57603d54975050505050505050610894565b6000613cf18c828d6001811115613cdd57fe5b14613ce9576000613cec565b60015b611813565b90506000613d05848663ffffffff61386016565b90506000613d2a83610877670de0b6b3a7640000603c546138bd90919063ffffffff16565b9050613d50613841670de0b6b3a764000061087761382c8582888563ffffffff6138bd16565b9a5050505050505050505050610894565b600082820183811015610894576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600080613dc88585613e6e565b90506000915082811015613de657610890838263ffffffff61386016565b509392505050565b60006003821115613e31575080600160028204015b81811015613e2b57809150600281828581613e1a57fe5b040181613e2357fe5b049050613e03565b50611797565b811561179757506001919050565b6000613e4a82614051565b6ec097ce7bc90715b34b9f100000000081613e6157fe5b0492915050565b303b1590565b6000806000846001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015613eab57600080fd5b505afa158015613ebf573d6000803e3d6000fd5b505050506040513d6040811015613ed557600080fd5b5080516020909101519092509050600080856001811115613ef257fe5b14613f6e57604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b158015613f3d57600080fd5b505afa158015613f51573d6000803e3d6000fd5b505050506040513d6020811015613f6757600080fd5b5051613fe1565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015613fb457600080fd5b505afa158015613fc8573d6000803e3d6000fd5b505050506040513d6020811015613fde57600080fd5b50515b9695505050505050565b6000610894670de0b6b3a7640000610877614019603d54670de0b6b3a764000061386090919063ffffffff16565b6124998787611813565b6000610894670de0b6b3a7640000610877614019603d54670de0b6b3a7640000613d6190919063ffffffff16565b60385460408051632e4c697f60e01b81526725b94542080c8000600482018190526024820185905291516000936001600160a01b031691632e4c697f916044808301926020929190829003018186803b1580156140ad57600080fd5b505afa1580156140c1573d6000803e3d6000fd5b505050506040513d60208110156140d757600080fd5b5051939250505056fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e657273686970416c726561647920696e697469616c697a65642c20757365206e6f6d696e6174654e65774f776e65724f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a65645468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e747261637420697320706175736564a265627a7a723158201983215b1d3a52f153b1a33e58e0d676fb473dad00152b998b94ce1ec637121964736f6c63430005100032

Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.