ETH Price: $3,421.85 (+0.50%)
Gas: 7 Gwei

Contract

0x868845f1dC7CCc15BCe50d7c90E1E644971cfe10
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Meta Fill Orders107176932020-08-23 16:35:181431 days ago1598200518IN
0x868845f1...4971cfe10
0 ETH0.0243933697
Meta Fill Orders107120712020-08-22 19:49:501431 days ago1598125790IN
0x868845f1...4971cfe10
0 ETH0.0178543771
Meta Fill Orders107051372020-08-21 18:15:441432 days ago1598033744IN
0x868845f1...4971cfe10
0 ETH0.04370108164
Meta Fill Orders106989082020-08-20 19:10:521433 days ago1597950652IN
0x868845f1...4971cfe10
0 ETH0.0263764799
Meta Fill Orders106915402020-08-19 16:09:101435 days ago1597853350IN
0x868845f1...4971cfe10
0 ETH0.03916815147
Meta Fill Orders106915362020-08-19 16:08:021435 days ago1597853282IN
0x868845f1...4971cfe10
0 ETH0.03695535147
Meta Fill Orders106867992020-08-18 22:37:451435 days ago1597790265IN
0x868845f1...4971cfe10
0 ETH0.0278601994
Meta Fill Orders106862512020-08-18 20:34:231435 days ago1597782863IN
0x868845f1...4971cfe10
0 ETH0.0293525199
Meta Fill Orders106835262020-08-18 10:51:421436 days ago1597747902IN
0x868845f1...4971cfe10
0 ETH0.04815148130
Meta Fill Orders106835202020-08-18 10:49:421436 days ago1597747782IN
0x868845f1...4971cfe10
0 ETH0.03570966134
Meta Fill Orders106829112020-08-18 8:33:091436 days ago1597739589IN
0x868845f1...4971cfe10
0 ETH0.05760161125.4
Meta Fill Orders106822162020-08-18 5:58:311436 days ago1597730311IN
0x868845f1...4971cfe10
0 ETH0.04889755132
Meta Fill Orders106820222020-08-18 5:16:011436 days ago1597727761IN
0x868845f1...4971cfe10
0 ETH0.03318334132
Meta Fill Orders106806652020-08-18 0:07:141436 days ago1597709234IN
0x868845f1...4971cfe10
0 ETH0.0242435891
Meta Fill Orders106793102020-08-17 19:04:491436 days ago1597691089IN
0x868845f1...4971cfe10
0 ETH0.02589224103
Meta Fill Orders106793102020-08-17 19:04:491436 days ago1597691089IN
0x868845f1...4971cfe10
0 ETH0.0266397100
Meta Fill Orders106792652020-08-17 18:54:541436 days ago1597690494IN
0x868845f1...4971cfe10
0 ETH0.0605922120
Meta Fill Orders106791042020-08-17 18:19:581436 days ago1597688398IN
0x868845f1...4971cfe10
0 ETH0.03196968120
Meta Fill Orders106790502020-08-17 18:06:061436 days ago1597687566IN
0x868845f1...4971cfe10
0 ETH0.03223694121
Meta Fill Orders106788472020-08-17 17:20:451436 days ago1597684845IN
0x868845f1...4971cfe10
0 ETH0.0616542154
Meta Fill Orders106788262020-08-17 17:15:571436 days ago1597684557IN
0x868845f1...4971cfe10
0 ETH0.04262416160
Meta Fill Orders106787082020-08-17 16:51:001437 days ago1597683060IN
0x868845f1...4971cfe10
0 ETH0.04556141171
Meta Fill Orders106786822020-08-17 16:45:591437 days ago1597682759IN
0x868845f1...4971cfe10
0 ETH0.04556568171
Meta Fill Orders106786142020-08-17 16:31:101437 days ago1597681870IN
0x868845f1...4971cfe10
0 ETH0.04608668173
Meta Fill Orders106786122020-08-17 16:31:011437 days ago1597681861IN
0x868845f1...4971cfe10
0 ETH0.05098527172
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FillOrder

Compiler Version
v0.5.16+commit.9c3226ce

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU GPLv3 license
File 1 of 44 : FillOrder.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "./BaseFillOrder.sol";
import "../../interfaces/trading/IFillOrder.sol";
import "../../interfaces/trading/IEIP712FillHasher.sol";


/// @title MultiFillOrder
/// @author Julian Wilson <[email protected]>
/// @notice Manages the public functionality to fill multiple orders at once
contract FillOrder is IFillOrder, BaseFillOrder {

    IEIP712FillHasher internal eip712FillHasher;

    constructor(ISuperAdminRole _superAdminRole, IEIP712FillHasher _eip712FillHasher) public BaseFillOrder(_superAdminRole) {
        eip712FillHasher = _eip712FillHasher;
    }

    /// @notice Fills a bunch of orders simulatenously.
    /// @param fillDetails The fills to execute.
    /// @param executorSig The signature of the executor on this fill if the executor is set.
    function fillOrders(
        LibOrder.FillDetails memory fillDetails,
        bytes memory executorSig
    )
        public
    {
        address executor = fillDetails.fills.orders[0].executor;
        bytes32 fillHash;

        require(
            fillDetails.fills.orders.length == fillDetails.fills.takerAmounts.length &&
            fillDetails.fills.orders.length == fillDetails.fills.makerSigs.length,
            "INCORRECT_ARRAY_LENGTHS"
        );

        if (executor != address(0)) {
            fillHash = eip712FillHasher.getDetailsHash(fillDetails);

            require(
                fills.getFillHashSubmitted(fillHash) == false,
                "FILL_ALREADY_SUBMITTED"
            );

            require(
                ECDSA.recover(
                    fillHash,
                    executorSig
                ) == executor,
                "EXECUTOR_SIGNATURE_MISMATCH"
            );

            if (fillDetails.fills.orders.length > 1) {
                for (uint256 i = 1; i < fillDetails.fills.orders.length; i++) {
                    require(
                        fillDetails.fills.orders[i].executor == executor,
                        "INCONSISTENT_EXECUTORS"
                    );
                }
            }

            fills.setFillHashSubmitted(fillHash);
        }

        _fillOrders(
            fillDetails.fills.orders,
            fillDetails.fills.takerAmounts,
            fillDetails.fills.makerSigs,
            msg.sender,
            fillHash
        );

    }

    /// @notice Fills a bunch of orders simulatenously in meta fashion
    /// @param fillDetails The details of the fill
    /// @param taker The taker for this fill.
    /// @param takerSig The signature of the taker for this fill.
    /// @param executorSig The signature of the executor on this order if the executor is set.
    function metaFillOrders(
        LibOrder.FillDetails memory fillDetails,
        address taker,
        bytes memory takerSig,
        bytes memory executorSig
    )
        public
    {
        bytes32 fillHash = eip712FillHasher.getDetailsHash(fillDetails);

        require(
            ECDSA.recover(
                fillHash,
                takerSig
            ) == taker,
            "TAKER_SIGNATURE_MISMATCH"
        );

        require(
            fills.getFillHashSubmitted(fillHash) == false,
            "FILL_ALREADY_SUBMITTED"
        );

        address executor = fillDetails.fills.orders[0].executor;

        if (executor != address(0)) {
            require(
                msg.sender == executor,
                "SENDER_MUST_BE_EXECUTOR"
            );
            require(
                ECDSA.recover(
                    fillHash,
                    executorSig
                ) == executor,
                "EXECUTOR_SIGNATURE_MISMATCH"
            );
        }

        require(
            fillDetails.fills.orders.length == fillDetails.fills.takerAmounts.length &&
            fillDetails.fills.orders.length == fillDetails.fills.makerSigs.length,
            "INCORRECT_ARRAY_LENGTHS"
        );

        if (fillDetails.fills.orders.length > 1) {
            for (uint256 i = 1; i < fillDetails.fills.orders.length; i++) {
                require(
                    fillDetails.fills.orders[i].executor == executor,
                    "INCONSISTENT_EXECUTORS"
                );
            }
        }

        _fillOrders(
            fillDetails.fills.orders,
            fillDetails.fills.takerAmounts,
            fillDetails.fills.makerSigs,
            taker,
            fillHash
        );

        fills.setFillHashSubmitted(fillHash);
    }

    /// @notice Internal method to fill multiple orders.
    ///         Checks if the fill can be optimized for the taker (i.e., transfers can be combined).
    /// @param makerOrders The orders to fill.
    /// @param takerAmounts The amount to fill for each order.
    /// @param makerSigs The maker signatures for each order.
    /// @param taker The taker of these orders.
    /// @param fillHash The fill hash, if applicable in the case of a meta fill.
    function _fillOrders(
        LibOrder.Order[] memory makerOrders,
        uint256[] memory takerAmounts,
        bytes[] memory makerSigs,
        address taker,
        bytes32 fillHash
    )
        private
    {
        bool areOrdersSimilar = areOrdersValidAndSimilar(
            makerOrders,
            takerAmounts,
            makerSigs,
            taker
        );
        // If we get here they are valid so no need to check again

        if (areOrdersSimilar) {
            _fillSimilarOrders(
                makerOrders,
                takerAmounts,
                taker,
                fillHash
            );
        } else {
            for (uint256 i = 0; i < makerOrders.length; i++) {
                _fillSingleOrder(
                    makerOrders[i],
                    takerAmounts[i],
                    taker,
                    fillHash
                );
            }
        }
    }

    /// @notice Internal method to fill multiple similar orders
    ///         Here, the taker transfers are batched to save gas.
    /// @param makerOrders The orders to fill.
    /// @param takerAmounts The amount to fill for each order.
    /// @param taker The taker of these orders.
    /// @param fillHash The fill hash, if applicable in the case of a meta fill.
    function _fillSimilarOrders(
        LibOrder.Order[] memory makerOrders,
        uint256[] memory takerAmounts,
        address taker,
        bytes32 fillHash
    )
        private
    {
        LibOrderAmounts.OrderAmounts memory totalOrderAmounts = LibOrderAmounts.computeTotalOrderAmounts(
            makerOrders,
            takerAmounts
        );

        settleOrderForTaker(
            makerOrders[0],
            totalOrderAmounts,
            taker
        );

        settleOrdersForMaker(
            makerOrders,
            takerAmounts,
            taker,
            fillHash
        );
    }

    /// @notice Checks if orders are valid and similar.
    ///         If they are, then we can optimize the fill
    /// @param makerOrders The orders to fill.
    /// @param takerAmounts The amount to fill for each order.
    /// @param makerSigs The maker signatures for each order.
    /// @param taker The taker of these orders.
    function areOrdersValidAndSimilar(
        LibOrder.Order[] memory makerOrders,
        uint256[] memory takerAmounts,
        bytes[] memory makerSigs,
        address taker
    )
        private
        view
        returns (bool)
    {
        bool isMakerBettingOutcomeOne = makerOrders[0].isMakerBettingOutcomeOne;
        bytes32 marketHash = makerOrders[0].marketHash;
        address baseToken = makerOrders[0].baseToken;

        for (uint256 i = 0; i < makerOrders.length; i++) {
            assertOrderValid(
                makerOrders[i],
                takerAmounts[i],
                taker,
                makerSigs[i]
            );
        }

        if (makerOrders.length > 1) {
            for (uint256 i = 1; i < makerOrders.length; i++) {
                if (makerOrders[i].isMakerBettingOutcomeOne != isMakerBettingOutcomeOne ||
                    makerOrders[i].marketHash != marketHash ||
                    makerOrders[i].baseToken != baseToken
                ) {
                    return false;
                }
            }
        }
        return true;
    }

    /// @notice Settles multiple orders for the maker at once.
    /// @param makerOrders The orders to fill.
    /// @param takerAmounts The amount to fill for each order.
    /// @param taker The taker of these orders.
    /// @param fillHash The fill hash, if applicable in the case of a meta fill.
    function settleOrdersForMaker(
        LibOrder.Order[] memory makerOrders,
        uint256[] memory takerAmounts,
        address taker,
        bytes32 fillHash
    )
        private
    {
        for (uint256 i = 0; i < makerOrders.length; i++) {
            LibOrderAmounts.OrderAmounts memory orderAmounts = LibOrderAmounts.computeOrderAmounts(
                makerOrders[i],
                takerAmounts[i]
            );

            uint256 newFillAmount = fills.fill(makerOrders[i], orderAmounts.takerAmount);

            settleOrderForMaker(
                makerOrders[i],
                orderAmounts
            );

            emit OrderFill(
                makerOrders[i].maker,
                makerOrders[i].marketHash,
                taker,
                newFillAmount,
                makerOrders[i].getOrderHash(),
                fillHash,
                makerOrders[i],
                orderAmounts
            );
        }
    }
}

File 2 of 44 : AffiliateRegistry.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../interfaces/IAffiliateRegistry.sol";
import "../interfaces/permissions/IWhitelist.sol";


contract AffiliateRegistry is IAffiliateRegistry {
    uint256 public constant MAX_AFFILIATE_FEE = 3*(10**19);

    IWhitelist private systemParamsWhitelist;

    address private defaultAffiliate;
    mapping (address => address) private addressToAffiliate;
    mapping (address => uint256) private affiliateFeeFrac;

    event AffiliateSet(
        address member,
        address affiliate
    );

    event AffiliateFeeFracSet(
        address affiliate,
        uint256 feeFrac
    );

    constructor(IWhitelist _systemParamsWhitelist) public {
        systemParamsWhitelist = _systemParamsWhitelist;
    }

    /// @notice Throws if the caller is not a system params admin.
    modifier onlySystemParamsAdmin() {
        require(
            systemParamsWhitelist.getWhitelisted(msg.sender),
            "NOT_SYSTEM_PARAM_ADMIN"
        );
        _;
    }

    /// @notice Sets the affiliate for an address.
    /// @param member The address to attach to the affiliate.
    /// @param affiliate The affiliate address to attach.
    function setAffiliate(address member, address affiliate)
        public
        onlySystemParamsAdmin
    {
        require(
            affiliate != address(0),
            "AFFILIATE_ZERO_ADDRESS"
        );

        addressToAffiliate[member] = affiliate;
    }

    /// @notice Sets the affiliate fee fraction for an address.
    /// @param affiliate The affiliate whose fee fraction should be changed.
    /// @param feeFrac The new fee fraction for this affiliate.
    function setAffiliateFeeFrac(address affiliate, uint256 feeFrac)
        public
        onlySystemParamsAdmin
    {
        require(
            feeFrac < MAX_AFFILIATE_FEE,
            "AFFILIATE_FEE_TOO_HIGH"
        );

        affiliateFeeFrac[affiliate] = feeFrac;
    }

    /// @notice Sets the default affiliate if no affiliate is set for an address.
    /// @param affiliate The new default affiliate.
    function setDefaultAffiliate(address affiliate)
        public
        onlySystemParamsAdmin
    {
        require(
            affiliate != address(0),
            "AFFILIATE_ZERO_ADDRESS"
        );

        defaultAffiliate = affiliate;
    }

    /// @notice Gets the affiliate for an address. If no affiliate is set, it returns the
    ///         default affiliate.
    /// @param member The address to query.
    /// @return The affiliate for this address.
    function getAffiliate(address member)
        public
        view
        returns (address)
    {
        address affiliate = addressToAffiliate[member];
        if (affiliate == address(0)) {
            return defaultAffiliate;
        } else {
            return affiliate;
        }
    }

    function getAffiliateFeeFrac(address affiliate)
        public
        view
        returns (uint256)
    {
        return affiliateFeeFrac[affiliate];
    }

    function getDefaultAffiliate()
        public
        view
        returns (address)
    {
        return defaultAffiliate;
    }

}

File 3 of 44 : Escrow.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../libraries/LibOutcome.sol";
import "../libraries/LibOrder.sol";
import "../interfaces/trading/IFillOrder.sol";
import "../interfaces/trading/IFeeSchedule.sol";
import "../interfaces/ISystemParameters.sol";
import "../interfaces/IOutcomeReporter.sol";
import "../interfaces/IAffiliateRegistry.sol";
import "../interfaces/IEscrow.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";

/// @title Escrow
/// @author Julian Wilson <[email protected]>
/// @notice Central location that stores all escrow when
///         swaps are traded.
contract Escrow is IEscrow {
    using SafeMath for uint256;

    ISystemParameters private systemParameters;
    IFillOrder private fillOrder;
    IOutcomeReporter private outcomeReporter;
    IFeeSchedule private feeSchedule;
    IAffiliateRegistry private affiliateRegistry;

    // marketHash => baseToken => owner => side => amount
    mapping(bytes32 => mapping(address => mapping(address => mapping(uint8 => uint256)))) returnAmounts;
    mapping(bytes32 => mapping(address => mapping(address => mapping(uint8 => uint256)))) stakedAmounts;

    struct BetFee {
        uint256 oracleFee;
        uint256 affiliateFee;
    }

    event BetSettled(
        address indexed owner,
        bytes32 indexed marketHash,
        address indexed baseToken,
        LibOutcome.Outcome outcome,
        uint256 settledAmount,
        uint256 oracleFeeAmount,
        uint256 affiliateFeeAmount
    );

    constructor(
        ISystemParameters _systemParameters,
        IFillOrder _fillOrder,
        IOutcomeReporter _outcomeReporter,
        IFeeSchedule _feeSchedule,
        IAffiliateRegistry _affiliateRegistry
    ) public {
        systemParameters = _systemParameters;
        fillOrder = _fillOrder;
        outcomeReporter = _outcomeReporter;
        feeSchedule = _feeSchedule;
        affiliateRegistry = _affiliateRegistry;
    }

    /// @notice Throws if the caller is not the FillOrder contract.
    modifier onlyFillOrder() {
        require(msg.sender == address(fillOrder), "ONLY_FILL_ORDER");
        _;
    }

    /// @notice Throws if the market's tokens are not redeemable.
    /// @param marketHash The market to check.
    modifier marketTokensRedeemable(bytes32 marketHash) {
        require(isMarketRedeemable(marketHash), "INVALID_REDEMPTION_TIME");
        _;
    }

    /// @notice Redeems outcome one or outcome two return amounts after a market
    ///         has been resolved.
    /// @param owner The user to redeem for.
    /// @param marketHash The market that is resolved.
    /// @param baseTokenAddress The token to resolve.
    function settleBet(
        address owner,
        bytes32 marketHash,
        address baseTokenAddress
    ) public marketTokensRedeemable(marketHash) {
        IERC20 baseToken = IERC20(baseTokenAddress);
        LibOutcome.Outcome marketResult = outcomeReporter.getReportedOutcome(
            marketHash
        );
        uint256 outcomeOneEligibility = returnAmounts[marketHash][baseTokenAddress][owner][uint8(
            LibOutcome.Outcome.OUTCOME_ONE
        )];
        uint256 outcomeTwoEligibility = returnAmounts[marketHash][baseTokenAddress][owner][uint8(
            LibOutcome.Outcome.OUTCOME_TWO
        )];
        uint256 outcomeOneStake = stakedAmounts[marketHash][baseTokenAddress][owner][uint8(
            LibOutcome.Outcome.OUTCOME_ONE
        )];
        uint256 outcomeTwoStake = stakedAmounts[marketHash][baseTokenAddress][owner][uint8(
            LibOutcome.Outcome.OUTCOME_TWO
        )];
        BetFee memory betFees;
        uint256 payout;

        if (
            marketResult == LibOutcome.Outcome.OUTCOME_ONE &&
            outcomeOneEligibility > 0
        ) {
            uint256 profits = outcomeOneEligibility.sub(outcomeOneStake);
            betFees = settleFees(baseTokenAddress, owner, profits);
            payout = outcomeOneEligibility.sub(betFees.oracleFee).sub(
                betFees.affiliateFee
            );
            returnAmounts[marketHash][baseTokenAddress][owner][uint8(
                LibOutcome.Outcome.OUTCOME_ONE
            )] = 0;
        } else if (
            marketResult == LibOutcome.Outcome.OUTCOME_TWO &&
            outcomeTwoEligibility > 0
        ) {
            uint256 profits = outcomeTwoEligibility.sub(outcomeTwoStake);
            betFees = settleFees(baseTokenAddress, owner, profits);
            payout = outcomeTwoEligibility.sub(betFees.oracleFee).sub(
                betFees.affiliateFee
            );
            returnAmounts[marketHash][baseTokenAddress][owner][uint8(
                LibOutcome.Outcome.OUTCOME_TWO
            )] = 0;
        } else if (
            marketResult == LibOutcome.Outcome.VOID &&
            (outcomeOneStake > 0 || outcomeTwoStake > 0)
        ) {
            if (outcomeOneStake > 0) {
                payout = outcomeOneStake;
                stakedAmounts[marketHash][baseTokenAddress][owner][uint8(
                    LibOutcome.Outcome.OUTCOME_ONE
                )] = 0;
            }
            if (outcomeTwoStake > 0) {
                payout = payout.add(outcomeTwoStake);
                stakedAmounts[marketHash][baseTokenAddress][owner][uint8(
                    LibOutcome.Outcome.OUTCOME_TWO
                )] = 0;
            }
        } else {
            revert("MARKET_WRONG_RESOLUTION");
        }

        require(baseToken.transfer(owner, payout), "CANNOT_TRANSFER_ESCROW");

        emit BetSettled(
            owner,
            marketHash,
            baseTokenAddress,
            marketResult,
            payout,
            betFees.oracleFee,
            betFees.affiliateFee
        );
    }

    /// @notice Updates the user's escrowed amount they have in the market.
    /// @param marketHash The market to redeem.
    /// @param baseToken The token with which they are betting.
    /// @param user The user to update.
    /// @param outcome The side to update.
    /// @param amount The amount to add.
    function updateStakedAmount(
        bytes32 marketHash,
        address baseToken,
        address user,
        LibOutcome.Outcome outcome,
        uint256 amount
    ) public onlyFillOrder {
        stakedAmounts[marketHash][baseToken][user][uint8(
            outcome
        )] = stakedAmounts[marketHash][baseToken][user][uint8(outcome)].add(
            amount
        );
    }

    /// @notice Updates the user's return amount
    /// @param marketHash The market for which they are betting on outcome one.
    /// @param baseToken The token with which they are betting.
    /// @param user The user to update.
    /// @param outcome The outcome to increase
    /// @param amount The amount to add.
    function increaseReturnAmount(
        bytes32 marketHash,
        address baseToken,
        address user,
        LibOutcome.Outcome outcome,
        uint256 amount
    ) public onlyFillOrder {
        returnAmounts[marketHash][baseToken][user][uint8(
            outcome
        )] = returnAmounts[marketHash][baseToken][user][uint8(outcome)].add(
            amount
        );
    }

    /// @notice Checks if the market's tokens are redeemable.
    /// @param marketHash The market to check.
    /// @return true if the market's tokens are redeemable, false otherwise.
    function isMarketRedeemable(bytes32 marketHash) public view returns (bool) {
        uint256 reportTime = outcomeReporter.getReportTime(marketHash);
        if (reportTime > 0) {
            return now > reportTime;
        } else {
            return false;
        }
    }

    /// @notice Checks if the owner has a valid redeemable bet.
    /// @param owner The owner of the bet.
    /// @param marketHash The market to check.
    /// @param baseToken The base token to check.
    /// @return true if the owner has a valid redeemable bet for this market, false otherwise.
    function getEligibility(
        address owner,
        bytes32 marketHash,
        address baseToken
    ) public view returns (Eligibility memory eligibility) {
        if (!isMarketRedeemable(marketHash)) {
            return
                Eligibility({
                    hasEligibility: false,
                    outcome: LibOutcome.Outcome.VOID,
                    amount: 0
                });
        }
        LibOutcome.Outcome marketResult = outcomeReporter.getReportedOutcome(
            marketHash
        );

        uint256 outcomeOneEligibility = returnAmounts[marketHash][baseToken][owner][uint8(
            LibOutcome.Outcome.OUTCOME_ONE
        )];
        uint256 outcomeTwoEligibility = returnAmounts[marketHash][baseToken][owner][uint8(
            LibOutcome.Outcome.OUTCOME_TWO
        )];
        uint256 outcomeOneStake = stakedAmounts[marketHash][baseToken][owner][uint8(
            LibOutcome.Outcome.OUTCOME_ONE
        )];
        uint256 outcomeTwoStake = stakedAmounts[marketHash][baseToken][owner][uint8(
            LibOutcome.Outcome.OUTCOME_TWO
        )];

        if (
            marketResult == LibOutcome.Outcome.OUTCOME_ONE &&
            outcomeOneEligibility > 0
        ) {
            return
                Eligibility({
                    hasEligibility: true,
                    outcome: LibOutcome.Outcome.OUTCOME_ONE,
                    amount: outcomeOneEligibility
                });
        } else if (
            marketResult == LibOutcome.Outcome.OUTCOME_TWO &&
            outcomeTwoEligibility > 0
        ) {
            return
                Eligibility({
                    hasEligibility: true,
                    outcome: LibOutcome.Outcome.OUTCOME_TWO,
                    amount: outcomeTwoEligibility
                });
        } else if (
            marketResult == LibOutcome.Outcome.VOID &&
            (outcomeOneStake > 0 || outcomeTwoStake > 0)
        ) {
            return
                Eligibility({
                    hasEligibility: true,
                    outcome: LibOutcome.Outcome.VOID,
                    amount: outcomeOneStake.add(outcomeTwoStake)
                });
        } else {
            return
                Eligibility({
                    hasEligibility: false,
                    outcome: LibOutcome.Outcome.VOID,
                    amount: 0
                });
        }
    }

    function getReturnAmount(
        bytes32 marketHash,
        address baseToken,
        address owner,
        LibOutcome.Outcome outcome
    ) public view returns (uint256) {
        return returnAmounts[marketHash][baseToken][owner][uint8(outcome)];
    }

    function getStakedAmount(
        bytes32 marketHash,
        address baseToken,
        address owner,
        LibOutcome.Outcome outcome
    ) public view returns (uint256) {
        return stakedAmounts[marketHash][baseToken][owner][uint8(outcome)];
    }

    /// @notice Settles fees for an owner and for a market.
    /// @param baseToken The token to settle.
    /// @param owner The owner.
    /// @param profits How much profit the owner made off this bet.
    /// @return The fees that were settled.
    function settleFees(address baseToken, address owner, uint256 profits)
        private
        returns (BetFee memory)
    {
        address affiliate = affiliateRegistry.getAffiliate(owner);
        uint256 affiliateFeeFrac = affiliateRegistry.getAffiliateFeeFrac(
            affiliate
        );

        uint256 oracleFee = settleOracleFee(baseToken, profits);
        uint256 affiliateFee = settleAffiliateFee(
            baseToken,
            profits,
            affiliate,
            affiliateFeeFrac
        );

        return BetFee({oracleFee: oracleFee, affiliateFee: affiliateFee});
    }

    /// @notice Settles the affiliate fee for a market.
    /// @param baseToken The token to settle.
    /// @param profits The profits made on the bet.
    /// @param affiliate The affiliate set for the winner of the bet.
    /// @param affiliateFeeFrac The fee assigned to this affiliate.
    /// @return The affiliate fee paid.
    function settleAffiliateFee(
        address baseToken,
        uint256 profits,
        address affiliate,
        uint256 affiliateFeeFrac
    ) private returns (uint256) {
        IERC20 token = IERC20(baseToken);
        uint256 affiliateFeeAmount = profits.mul(affiliateFeeFrac).div(
            LibOrder.getOddsPrecision()
        );
        if (affiliateFeeAmount > 0) {
            require(
                token.transfer(affiliate, affiliateFeeAmount),
                "CANNOT_TRANSFER_AFFILIATE_FEE"
            );
        }
        return affiliateFeeAmount;
    }

    /// @notice Calculates oracle fee to be paid based on the market profits
    /// @param baseToken The base token to settle.
    /// @param profits Profit of user's outcome eligibility.
    /// @return The amount oracle fee to be paid.
    function settleOracleFee(address baseToken, uint256 profits)
        private
        returns (uint256)
    {
        IERC20 token = IERC20(baseToken);
        uint256 oracleFee = feeSchedule.getOracleFees(baseToken);
        uint256 oracleFeeAmount = profits.mul(oracleFee).div(
            LibOrder.getOddsPrecision()
        );
        address oracleFeeRecipient = systemParameters.getOracleFeeRecipient();

        if (oracleFeeAmount > 0) {
            require(
                token.transfer(oracleFeeRecipient, oracleFeeAmount),
                "CANNOT_TRANSFER_FEE"
            );
        }
        return oracleFeeAmount;
    }
}

File 4 of 44 : Initializable.sol
pragma solidity 0.5.16;


contract Initializable {
    bool public initialized;

    /// @notice Throws if this contract has already been initialized.
    modifier notInitialized() {
        require(!initialized, "ALREADY_INITIALIZED");
        _;
    }
}

File 5 of 44 : Migrations.sol
//solhint-disable

pragma solidity 0.5.16;

contract Migrations {
    address public owner;
    uint public last_completed_migration;

    constructor() public {
        owner = msg.sender;
    }

    modifier restricted() {
        if (msg.sender == owner) _;
    }

    function setCompleted(uint completed) public restricted {
        last_completed_migration = completed;
    }

    function upgrade(address new_address) public restricted {
        Migrations upgraded = Migrations(new_address);
        upgraded.setCompleted(last_completed_migration);
    }
}

File 6 of 44 : OutcomeReporter.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../libraries/LibOutcome.sol";
import "../interfaces/IOutcomeReporter.sol";
import "../interfaces/permissions/IWhitelist.sol";
import "./Initializable.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";

/// @title OutcomeReporter
/// @author Julian Wilson <[email protected]>
/// @notice Allows OutcomeReporter admins to report an initial outcome on an event.
contract OutcomeReporter is IOutcomeReporter {
    using SafeMath for uint256;

    IWhitelist private outcomeReporterWhitelist;

    mapping(bytes32 => LibOutcome.Outcome) private reportedOutcomes;
    mapping(bytes32 => uint256) private reportTime;

    event OutcomeReported(bytes32 marketHash, LibOutcome.Outcome outcome);

    constructor(
        IWhitelist _outcomeReporterWhitelist
    ) public {
        outcomeReporterWhitelist = _outcomeReporterWhitelist;
    }

    /// @notice Throws if the caller is not an Outcome Reporter admin.
    modifier onlyOutcomeReporterAdmin() {
        require(
            outcomeReporterWhitelist.getWhitelisted(msg.sender),
            "NOT_OUTCOME_REPORTER_ADMIN"
        );
        _;
    }

    /// @notice Throws if the market is already reported
    /// @param marketHash The market to check.
    modifier notAlreadyReported(bytes32 marketHash) {
        require(
            reportTime[marketHash] == 0,
            "MARKET_ALREADY_REPORTED"
        );
        _;
    }

    /// @notice Reports the initial outcome of the market.
    ///         Only callable by OutcomeReporter admins.
    ///         Can only be reported once.
    /// @param marketHash The market to report.
    /// @param reportedOutcome The outcome to report.
    function reportOutcome(bytes32 marketHash, LibOutcome.Outcome reportedOutcome)
        public
        onlyOutcomeReporterAdmin
        notAlreadyReported(marketHash)
    {
        reportedOutcomes[marketHash] = reportedOutcome;
        reportTime[marketHash] = now;

        emit OutcomeReported(marketHash, reportedOutcome);
    }

    /// @notice Reports the outcome for several markets.
    /// @param marketHashes The market hashes to report.
    /// @param outcomes The outcomes to report.
    function reportOutcomes(
        bytes32[] memory marketHashes,
        LibOutcome.Outcome[] memory outcomes
    ) public {
        uint256 marketHashesLength = marketHashes.length;
        for (uint256 i = 0; i < marketHashesLength; i++) {
            reportOutcome(marketHashes[i], outcomes[i]);
        }
    }

    function getReportedOutcome(bytes32 marketHash)
        public
        view
        returns (LibOutcome.Outcome)
    {
        return reportedOutcomes[marketHash];
    }

    function getReportTime(bytes32 marketHash) public view returns (uint256) {
        return reportTime[marketHash];
    }
}

File 7 of 44 : SystemParameters.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../interfaces/permissions/IWhitelist.sol";
import "../interfaces/ISystemParameters.sol";


/// @title SystemParameters
/// @author Julian Wilson <[email protected]>
/// @notice Stores system parameters.
contract SystemParameters is ISystemParameters {
    address private oracleFeeRecipient;

    IWhitelist private systemParamsWhitelist;

    constructor(IWhitelist _systemParamsWhitelist) public {
        systemParamsWhitelist = _systemParamsWhitelist;
    }

    /// @notice Throws if the caller is not a system params admin.
    modifier onlySystemParamsAdmin() {
        require(
            systemParamsWhitelist.getWhitelisted(msg.sender),
            "NOT_SYSTEM_PARAM_ADMIN"
        );
        _;
    }

    /// @notice Sets the oracle fee recipient. Only callable by SystemParams admins.
    /// @param newOracleFeeRecipient The new oracle fee recipient address
    function setNewOracleFeeRecipient(address newOracleFeeRecipient)
        public
        onlySystemParamsAdmin
    {
        oracleFeeRecipient = newOracleFeeRecipient;
    }

    function getOracleFeeRecipient() public view returns (address) {
        return oracleFeeRecipient;
    }
}

File 8 of 44 : OrderValidator.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;


import "../../libraries/LibOrderAmounts.sol";
import "../../libraries/LibString.sol";
import "../../libraries/LibOrder.sol";
import "../../interfaces/trading/IFeeSchedule.sol";
import "../../interfaces/trading/IFills.sol";
import "../../interfaces/trading/ITokenTransferProxy.sol";
import "../../interfaces/trading/IReadOnlyValidator.sol";
import "../../interfaces/IOutcomeReporter.sol";
import "../../interfaces/trading/IEIP712FillHasher.sol";
import "../../interfaces/extensions/IOrderValidator.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";


/// @title OrderValidator
/// @author Julian Wilson <[email protected]>
/// @notice Functions to validate orders off-chain and
///         return a user-friendly string.
///         None of these are used in the actual protocol to determine
///         any state changes.
contract OrderValidator is IOrderValidator {
    using LibOrder for LibOrder.Order;
    using LibString for string;
    using SafeMath for uint256;

    ITokenTransferProxy private proxy;
    IFills private fills;
    IFeeSchedule private feeSchedule;
    IEIP712FillHasher private eip712FillHasher;
    IOutcomeReporter private outcomeReporter;

    constructor(
        ITokenTransferProxy _proxy,
        IFills _fills,
        IFeeSchedule _feeSchedule,
        IEIP712FillHasher _eip712FillHasher,
        IOutcomeReporter _outcomeReporter
    ) public {
        proxy = _proxy;
        fills = _fills;
        feeSchedule = _feeSchedule;
        eip712FillHasher = _eip712FillHasher;
        outcomeReporter = _outcomeReporter;
    }

    /// @notice Gets the current status of an order without considering
    ///         any individual taker.
    /// @param order The order to examine.
    /// @param makerSig The signature of maker on this order.
    /// @return A string representing the status. "OK" for valid.
    function getOrderStatus(
        LibOrder.Order memory order,
        bytes memory makerSig
    )
        public
        view
        returns (string memory)
    {
        string memory baseMakerOrderStatus = getBaseOrderStatus(
            order,
            makerSig
        );
        if (!baseMakerOrderStatus.equals("OK")) {return baseMakerOrderStatus;}
        uint256 remainingSpace = fills.remainingSpace(order);
        if (remainingSpace == 0) {
            return "FULLY_FILLED";
        }
        LibOrderAmounts.OrderAmounts memory orderAmounts = LibOrderAmounts.computeOrderAmounts(
            order,
            remainingSpace
        );
        string memory allowanceBalanceValidity = getMakerAllowanceAndBalanceStatus(
            orderAmounts,
            order.baseToken,
            order.maker
        );
        return allowanceBalanceValidity;
    }

    /// @notice Gets the current status of multiple orders without considering
    ///         any individual taker.
    /// @param orders The orders to examine.
    /// @param makerSigs The signature of the makers on this order.
    /// @return A string representing the status. "OK" for valid.
    function getMultiOrderStatus(
        LibOrder.Order[] memory orders,
        bytes[] memory makerSigs
    )
        public
        view
        returns (string[] memory)
    {
        string[] memory statuses = new string[](orders.length);

        for (uint256 i = 0; i < orders.length; i++) {
            statuses[i] = getOrderStatus(
                orders[i],
                makerSigs[i]
            );
        }

        return statuses;
    }

    /// @notice Gets the status of a multi-order fill
    /// @param fillDetails The fills to execute
    /// @param executorSig The signature of the executor, if any.
    /// @param taker The hypothetical taker.
    /// @return A string representing the status. "OK" for valid.
    function getFillStatus(
        LibOrder.FillDetails memory fillDetails,
        bytes memory executorSig,
        address taker
    )
        public
        view
        returns (string memory)
    {
        address executor = fillDetails.fills.orders[0].executor;
        if (executor != address(0)) {
            bytes32 fillHash = eip712FillHasher.getDetailsHash(fillDetails);

            if (fills.getFillHashSubmitted(fillHash)) {
                return "FILL_ALREADY_SUBMITTED";
            }

            if (ECDSA.recover(fillHash, executorSig) != executor) {
                return "EXECUTOR_SIGNATURE_MISMATCH";
            }
        }

        if (fillDetails.fills.orders.length > 1) {
            for (uint256 i = 1; i < fillDetails.fills.orders.length; i++) {
                if (fillDetails.fills.orders[i].executor != executor) {
                    return "INCONSISTENT_EXECUTORS";
                }
            }
        }

        return _getFillStatus(
            fillDetails.fills.orders,
            taker,
            fillDetails.fills.takerAmounts,
            fillDetails.fills.makerSigs
        );
    }

    /// @notice Gets the status of a meta multi-order fill
    /// @param fillDetails The fills to execute, meta style.
    /// @param taker The hypothetical taker.
    /// @param takerSig The taker's signature for this fill.
    /// @param executorSig The signature of the executor, if any.
    /// @return A string representing the status. "OK" for valid.
    function getMetaFillStatus(
        LibOrder.FillDetails memory fillDetails,
        address taker,
        bytes memory takerSig,
        bytes memory executorSig
    )
        public
        view
        returns (string memory)
    {
        bytes32 fillHash = eip712FillHasher.getDetailsHash(fillDetails);

        if (ECDSA.recover(fillHash, takerSig) != taker) {
            return "TAKER_SIGNATURE_MISMATCH";
        }

        if (fills.getFillHashSubmitted(fillHash)) {
            return "FILL_ALREADY_SUBMITTED";
        }

        address executor = fillDetails.fills.orders[0].executor;

        if (executor != address(0) &&
            ECDSA.recover(fillHash, executorSig) != executor) {
            return "EXECUTOR_SIGNATURE_MISMATCH";
        }

        if (fillDetails.fills.orders.length > 1) {
            for (uint256 i = 1; i < fillDetails.fills.orders.length; i++) {
                if (fillDetails.fills.orders[i].executor != executor) {
                    return "INCONSISTENT_EXECUTORS";
                }
            }
        }

        return _getFillStatus(
            fillDetails.fills.orders,
            taker,
            fillDetails.fills.takerAmounts,
            fillDetails.fills.makerSigs
        );
    }

    /// @notice Gets the combined status of several orders considering
    ///         a single taker and a taker amount for each order.
    /// @param makerOrders The orders to fill.
    /// @param taker The hypothetical taker.
    /// @param takerAmounts The hypothetical amounts to fill.
    /// @param makerSigs The signatures of the makers on these orders.
    /// @return A string representing the status. "OK" for valid.
    function _getFillStatus(
        LibOrder.Order[] memory makerOrders,
        address taker,
        uint256[] memory takerAmounts,
        bytes[] memory makerSigs
    )
        private
        view
        returns (string memory)
    {
        string memory baseMultiFillStatus = getBaseMultiFillStatus(
            makerOrders,
            taker,
            takerAmounts,
            makerSigs
        );
        if (!baseMultiFillStatus.equals("OK")) {
            return baseMultiFillStatus;
        }
        return getMultiAllowanceBalanceStatus(
            makerOrders,
            takerAmounts,
            taker
        );
    }

    /// @notice Gets the "base" status of an order without considering any token
    ///         allowances and balances.
    /// @param order A maker order.
    /// @param makerSig The signature of the maker on this order.
    /// @return A string representing the status. "OK" for valid.
    function getBaseOrderStatus(
        LibOrder.Order memory order,
        bytes memory makerSig
    )
        private
        view
        returns (string memory)
    {
        string memory paramValidity = order.getParamValidity();
        if (paramValidity.equals("OK") == false) {return paramValidity;}
        if (outcomeReporter.getReportTime(order.marketHash) != 0) {
            return "MARKET_NOT_TRADEABLE";
        }
        if (order.checkSignature(makerSig) == false) {
            return "BAD_SIGNATURE";
        }
        if (fills.isOrderCancelled(order)) {
            return "CANCELLED";
        }
        return "OK";
    }

    /// @notice Checks the maker's balances and allowances for given order amounts
    /// @param orderAmounts The computed balances to transfer as a result of the fill.
    /// @param baseTokenAddress The base token to use.
    /// @param maker The maker's balance to check.
    /// @return A string representing the status. "OK" for valid.
    function getMakerAllowanceAndBalanceStatus(
        LibOrderAmounts.OrderAmounts memory orderAmounts,
        address baseTokenAddress,
        address maker
    )
        private
        view
        returns (string memory)
    {
        IERC20 baseToken = IERC20(baseTokenAddress);
        if (baseToken.balanceOf(maker) < orderAmounts.takerAmount) {
            return "MAKER_INSUFFICIENT_BASE_TOKEN";
        }
        if (baseToken.allowance(maker, address(proxy)) < orderAmounts.takerAmount) {
            return "MAKER_INSUFFICIENT_BASE_TOKEN_ALLOWANCE";
        }
        return "OK";
    }

    /// @notice Gets the status in terms of token balances
    ///         and allowances if several orders were to be filled by a
    ///         single taker.
    ///
    ///         For this method, we can combine the orders and treat it as
    ///         one big order for the taker, but still need to check each
    ///         order individually for makers.
    ///
    ///         Assumes base token is same for every order.
    /// @param makerOrders The hypothetical orders to fill.
    /// @param takerAmounts The hypothetical amounts to fill for each order.
    /// @param taker The taker filling these orders.
    /// @return A string representing the status. "OK" for valid.
    function getMultiAllowanceBalanceStatus(
        LibOrder.Order[] memory makerOrders,
        uint256[] memory takerAmounts,
        address taker
    )
        private
        view
        returns (string memory)
    {
        address baseToken = makerOrders[0].baseToken;

        LibOrderAmounts.OrderAmounts memory totalOrderAmounts = LibOrderAmounts.computeTotalOrderAmounts(
            makerOrders,
            takerAmounts
        );

        for (uint256 i = 0; i < makerOrders.length; i++) {
            LibOrderAmounts.OrderAmounts memory individualOrderAmounts = LibOrderAmounts.computeOrderAmounts(
                makerOrders[i],
                takerAmounts[i]
            );
            string memory makerAllowanceBalanceValidity = getMakerAllowanceAndBalanceStatus(
                individualOrderAmounts,
                baseToken,
                makerOrders[i].maker
            );
            if (!makerAllowanceBalanceValidity.equals("OK")) {
                return makerAllowanceBalanceValidity;
            }
        }
        return getTakerAllowanceAndBalanceStatus(
            totalOrderAmounts,
            baseToken,
            taker
        );
    }

    /// @notice Gets the combined base status of several orders considering
    ///         a single taker and a taker amount for each order.
    ///         Does not consider balances or allowances.
    ///         The markets must be identical in order to combine taker amounts.
    /// @param makerOrders The orders to fill.
    /// @param taker The hypothetical taker.
    /// @param takerAmounts The hypothetical amounts to fill.
    /// @param signatures The signatures of the makers on these orders.
    /// @return A string representing the status. "OK" for valid.
    function getBaseMultiFillStatus(
        LibOrder.Order[] memory makerOrders,
        address taker,
        uint256[] memory takerAmounts,
        bytes[] memory signatures
    )
        private
        view
        returns (string memory)
    {
        for (uint256 i = 0; i < makerOrders.length; i++) {
            if (makerOrders[i].marketHash != makerOrders[0].marketHash) {return "MARKETS_NOT_IDENTICAL";}
            if (makerOrders[i].baseToken != makerOrders[0].baseToken) {return "BASE_TOKENS_NOT_IDENTICAL";}
            // Don't have to compare directions - all that matters is the amount end of the day
            string memory baseMakerOrderStatus = getBaseFillStatus(
                makerOrders[i],
                signatures[i],
                takerAmounts[i],
                taker
            );
            if (!baseMakerOrderStatus.equals("OK")) {return baseMakerOrderStatus;}
        }
        return "OK";
    }

    /// @notice Checks the fillability of an order along with the taker amount.
    ///         Does not check balances.
    /// @param order The order to fill.
    /// @param makerSig The maker's signature.
    /// @param takerAmount The hypothetical taker amount.
    /// @param taker The taker.
    /// @return A string representing the status. "OK" for valid.
    function getBaseFillStatus(
        LibOrder.Order memory order,
        bytes memory makerSig,
        uint256 takerAmount,
        address taker
    )
        private
        view
        returns (string memory)
    {
        if (takerAmount == 0) {return "TAKER_AMOUNT_NOT_POSITIVE";}
        string memory baseMakerOrderStatus = getBaseOrderStatus(
            order,
            makerSig
        );
        if (!baseMakerOrderStatus.equals("OK")) {return baseMakerOrderStatus;}
        if (taker == order.maker) {return "TAKER_NOT_MAKER";}
        if (!fills.orderHasSpace(order, takerAmount)) {return "INSUFFICIENT_SPACE";}
        return "OK";
    }

    /// @notice Checks the taker's balances and allowances for a given order to be filled.
    /// @param orderAmounts The computed balances to transfer as a result of the fill.
    /// @param baseTokenAddress The base token address
    /// @param taker The hypothetical taker.
    /// @return A string representing the status. "OK" for valid.
    function getTakerAllowanceAndBalanceStatus(
        LibOrderAmounts.OrderAmounts memory orderAmounts,
        address baseTokenAddress,
        address taker
    )
        private
        view
        returns (string memory)
    {
        IERC20 baseToken = IERC20(baseTokenAddress);
        if (baseToken.balanceOf(taker) < orderAmounts.takerEscrow) {
            return "TAKER_INSUFFICIENT_BASE_TOKEN";
        }
        if (baseToken.allowance(taker, address(proxy)) < orderAmounts.takerEscrow) {
            return "TAKER_INSUFFICIENT_BASE_TOKEN_ALLOWANCE";
        }
        return "OK";
    }
}

File 9 of 44 : OutcomeReporterWhitelist.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "./Whitelist.sol";
import "../../interfaces/permissions/ISuperAdminRole.sol";


/// @title OutcomeReporterWhitelist
/// @author Julian Wilson <[email protected]>
/// @notice A whitelist that represents all members allowed to
///         report on markets in the protocol.
contract OutcomeReporterWhitelist is Whitelist {
    constructor(ISuperAdminRole _superAdminRole) public Whitelist(_superAdminRole) {}
}

File 10 of 44 : SuperAdminRole.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../interfaces/permissions/ISuperAdminRole.sol";
import "openzeppelin-solidity/contracts/access/Roles.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";


/// @title SuperAdminRole
/// @author Julian Wilson <[email protected]>
/// @notice This is copied from the [email protected] library CapperRole and just
///         renamed to SuperAdminRole. Super admins are parents to all other admins in the system.
///         Super admins can also promote others to super admins but not remove them.
contract SuperAdminRole is ISuperAdminRole {
    using Roles for Roles.Role;
    using SafeMath for uint256;

    event SuperAdminAdded(address indexed account);
    event SuperAdminRemoved(address indexed account);

    Roles.Role private superAdmins;

    uint256 private superAdminCount;

    constructor() public {
        _addSuperAdmin(msg.sender);
    }

    /// @notice Throws if the caller is not a super admin./
    modifier onlySuperAdmin() {
        require(isSuperAdmin(msg.sender), "NOT_SUPER_ADMIN");
        _;
    }

    /// @notice Adds a super admin to the list.
    /// @param account The account to add.
    function addSuperAdmin(address account) public onlySuperAdmin {
        _addSuperAdmin(account);
    }

    /// @notice Throws if the caller is last super admin left
    modifier atLeastOneSuperAdmin() {
        require(
            superAdminCount > 1,
            "LAST_SUPER_ADMIN"
        );
        _;
    }

    /// @notice Removes a super admin from the list.
    /// @param account The account to add.
    function removeSuperAdmin(address account)
        public
        onlySuperAdmin
        atLeastOneSuperAdmin
    {
        _removeSuperAdmin(account);
    }

    /// @notice Internal function to add an account to the super admin list.
    /// @param account The account to add.
    function _addSuperAdmin(address account) internal {
        superAdmins.add(account);
        superAdminCount = superAdminCount.add(1);
        emit SuperAdminAdded(account);
    }

    /// @notice Internal function to remove an account from the super admin list.
    /// @param account The account to remove.
    function _removeSuperAdmin(address account) internal {
        superAdmins.remove(account);
        superAdminCount = superAdminCount.sub(1);
        emit SuperAdminRemoved(account);
    }

        /// @notice Gets the total number of super admins.
    /// @return The total number of super admins.
    function getSuperAdminCount() public view returns (uint256) {
        return superAdminCount;
    }

    /// @notice Checks if an account is a super admin.
    /// @param account The account to add.
    /// @return true if the account is a super admin, false otherwise.
    function isSuperAdmin(address account) public view returns (bool) {
        return superAdmins.has(account);
    }
}

File 11 of 44 : SystemParamsWhitelist.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../interfaces/permissions/ISuperAdminRole.sol";
import "./Whitelist.sol";


/// @title OutcomeReporterWhitelist
/// @author Julian Wilson <[email protected]>
/// @notice A whitelist that represents all members allowed to
///         change parameters in the protocol.
contract SystemParamsWhitelist is Whitelist {
    constructor(ISuperAdminRole _superAdminRole) public Whitelist(_superAdminRole) {}
}

File 12 of 44 : Whitelist.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../interfaces/permissions/ISuperAdminRole.sol";
import "../../interfaces/permissions/IWhitelist.sol";


/// @title Whitelist
/// @author Julian Wilson <[email protected]>
/// @notice The Whitelist contract has a whitelist of addresses, and provides basic authorization control functions.
///         This simplifies the implementation of "user permissions".
///         This Whitelist is special in that only super admins can add others to this whitelist.
///         This is copied verbatim, plus the SuperAdminRole authorization, from openzeppelin.
contract Whitelist is IWhitelist {
    ISuperAdminRole internal superAdminRole;

    mapping (address => bool) public whitelisted;

    constructor(ISuperAdminRole _superAdminRole) public {
        superAdminRole = _superAdminRole;
    }

    /// @notice Throws if the operator is not a super admin.
    /// @param operator The operator.
    modifier onlySuperAdmin(address operator) {
        require(
            superAdminRole.isSuperAdmin(operator),
            "NOT_A_SUPER_ADMIN"
        );
        _;
    }

    /// @notice Adds an operator to the whitelist
    ///         Only callable by the SuperAdmin role.
    /// @param operator The operator to add.
    function addAddressToWhitelist(address operator)
        public
        onlySuperAdmin(msg.sender)
    {
        whitelisted[operator] = true;
    }

    /// @notice Removes an address from the whitelist
    ///         Only callable by the SuperAdmin role.
    /// @param operator The operator to remove.
    function removeAddressFromWhitelist(address operator)
        public
        onlySuperAdmin(msg.sender)
    {
        whitelisted[operator] = false;
    }

    /// @notice Checks if the operator is whitelisted.
    /// @param operator The operator.
    /// @return true if the operator is whitelisted, false otherwise
    function getWhitelisted(address operator) public view returns (bool) {
        return whitelisted[operator];
    }
}

File 13 of 44 : DAI.sol
pragma solidity 0.5.16;

/* solium-disable */

contract DAI {

    // --- ERC20 Data ---
    string  public constant name     = "Dai Stablecoin";
    string  public constant symbol   = "DAI";
    string  public constant version  = "1";
    uint8   public constant decimals = 18;
    uint256 public totalSupply;

    mapping (address => uint)                      public balanceOf;
    mapping (address => mapping (address => uint)) public allowance;
    mapping (address => uint)                      public nonces;

    event Approval(address indexed src, address indexed guy, uint wad);
    event Transfer(address indexed src, address indexed dst, uint wad);

    // --- Math ---
    function add(uint x, uint y) internal pure returns (uint z) {
        require((z = x + y) >= x);
    }
    function sub(uint x, uint y) internal pure returns (uint z) {
        require((z = x - y) <= x);
    }

    // --- EIP712 niceties ---
    bytes32 public DOMAIN_SEPARATOR;
    // bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)");
    bytes32 public constant PERMIT_TYPEHASH = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb;

    constructor(uint256 chainId_) public {
        DOMAIN_SEPARATOR = keccak256(abi.encode(
            keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
            keccak256(bytes(name)),
            keccak256(bytes(version)),
            chainId_,
            address(this)
        ));
    }

    // --- Token ---
    function transfer(address dst, uint wad) external returns (bool) {
        return transferFrom(msg.sender, dst, wad);
    }

    function transferFrom(address src, address dst, uint wad)
        public returns (bool)
    {
        require(balanceOf[src] >= wad, "Dai/insufficient-balance");
        if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) {
            require(allowance[src][msg.sender] >= wad, "Dai/insufficient-allowance");
            allowance[src][msg.sender] = sub(allowance[src][msg.sender], wad);
        }
        balanceOf[src] = sub(balanceOf[src], wad);
        balanceOf[dst] = add(balanceOf[dst], wad);
        emit Transfer(src, dst, wad);
        return true;
    }

    function burn(address usr, uint wad) external {
        require(balanceOf[usr] >= wad, "Dai/insufficient-balance");
        if (usr != msg.sender && allowance[usr][msg.sender] != uint(-1)) {
            require(allowance[usr][msg.sender] >= wad, "Dai/insufficient-allowance");
            allowance[usr][msg.sender] = sub(allowance[usr][msg.sender], wad);
        }
        balanceOf[usr] = sub(balanceOf[usr], wad);
        totalSupply    = sub(totalSupply, wad);
        emit Transfer(usr, address(0), wad);
    }

    function approve(address usr, uint wad) external returns (bool) {
        allowance[msg.sender][usr] = wad;
        emit Approval(msg.sender, usr, wad);
        return true;
    }

    function setBalance(address _target, uint256 _value) external {
        balanceOf[_target] = _value;
    }

    // --- Approve by signature ---
    function permit(address holder, address spender, uint256 nonce, uint256 expiry,
                    bool allowed, uint8 v, bytes32 r, bytes32 s) external
    {
        bytes32 digest =
            keccak256(abi.encodePacked(
                "\x19\x01",
                DOMAIN_SEPARATOR,
                keccak256(abi.encode(PERMIT_TYPEHASH,
                                     holder,
                                     spender,
                                     nonce,
                                     expiry,
                                     allowed))
        ));

        require(holder != address(0), "Dai/invalid-address-0");
        require(holder == ecrecover(digest, v, r, s), "Dai/invalid-permit");
        require(expiry == 0 || now <= expiry, "Dai/permit-expired");
        require(nonce == nonces[holder]++, "Dai/invalid-nonce");
        uint wad = allowed ? uint(-1) : 0;
        allowance[holder][spender] = wad;
        emit Approval(holder, spender, wad);
    }
}

File 14 of 44 : DetailedToken.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;


/// @title DetailedToken
/// @author Julian Wilson <[email protected]>
/// @notice A utility contract to help pull name, symbol and decimals
///         from ERC20 tokens.
///         Verbatim, this:
///         https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC20/ERC20Detailed.sol
contract DetailedToken {
    string private _name;
    string private _symbol;
    uint8 private _decimals;

    constructor (string memory name, string memory symbol, uint8 decimals) public {
        _name = name;
        _symbol = symbol;
        _decimals = decimals;
    }

    /// @notice Gets the name of the token.
    /// @return The name of the token.
    function name() public view returns (string memory) {
        return _name;
    }

    /// @notice Gets the symbol of the token.
    /// @return The symbol of the token.
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /// @notice Gets the decimals of the token.
    /// @return The decimals of the token.
    function decimals() public view returns (uint8) {
        return _decimals;
    }
}

File 15 of 44 : WETH.sol
pragma solidity 0.5.16;

import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";


contract WETH is IERC20 {
    using SafeMath for uint256;

    string public constant name = "SportX WETH";
    string public constant symbol = "WETH";
    string public constant version = "1";
    uint8 public constant decimals = 18;
    bytes2 constant private EIP191_HEADER = 0x1901;
    bytes32 public constant EIP712_UNWRAP_TYPEHASH = keccak256("Unwrap(address holder,uint256 amount,uint256 nonce,uint256 expiry)");
    bytes32 public constant EIP712_PERMIT_TYPEHASH = keccak256(
        "Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)"
    );
    bytes32 public EIP712_DOMAIN_SEPARATOR;
    uint256 private _totalSupply;
    address public defaultOperator;
    address public defaultOperatorController;

    mapping (address => uint256) private _balances;
    mapping (address => mapping (address => uint256)) private _allowed;
    mapping (address => uint256) public unwrapNonces;
    mapping (address => uint256) public permitNonces;

    event Deposit(address indexed dst, uint256 amount);
    event Withdrawal(address indexed src, uint256 amount);

    constructor (address _operator, uint256 _chainId, address _defaultOperatorController) public {
        defaultOperator = _operator;
        defaultOperatorController = _defaultOperatorController;
        EIP712_DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                keccak256(bytes(name)),
                keccak256(bytes(version)),
                _chainId,
                address(this)
            )
        );
    }

    modifier onlyDefaultOperatorController() {
        require(
            msg.sender == defaultOperatorController,
            "ONLY_DEFAULT_OPERATOR_CONTROLLER"
        );
        _;
    }

    /**
     * @dev Alias for the deposit function to deposit ETH.
     */
    function() external payable {
        _deposit(msg.sender, msg.value);
    }

    /**
     * @dev Sets the default operator. Only callable by the default operator controller.
     * @param newDefaultOperator The new default operator.
     */
    function setDefaultOperator(address newDefaultOperator) external onlyDefaultOperatorController {
        defaultOperator = newDefaultOperator;
    }

    /**
     * @dev Unwraps ETH meta style. Exchanges this token, WETH, for ETH 1 to 1
     * @param holder The holder of WETH that wishes to withdraw.
     * @param amount The amount to withdraw.
     * @param nonce The current nonce for this holder, to prevent replays of the withdraw.
     * @param expiry The time after which this meta withdraw is not valid.
     * @param v v parameter in the ECDSA signature.
     * @param r r parameter in the ECDSA signature.
     * @param s s parameter in the ECDSA signature.
     */
    function metaWithdraw(
        address payable holder,
        uint256 amount,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        bytes32 digest = keccak256(
            abi.encodePacked(
                EIP191_HEADER,
                EIP712_DOMAIN_SEPARATOR,
                keccak256(
                    abi.encode(
                        EIP712_UNWRAP_TYPEHASH,
                        holder,
                        amount,
                        nonce,
                        expiry
                    )
                )
            )
        );

        require(holder != address(0), "INVALID_HOLDER");
        require(holder == ecrecover(digest, v, r, s), "INVALID_SIGNATURE");
        require(expiry == 0 || now <= expiry, "META_WITHDRAW_EXPIRED");
        require(nonce == unwrapNonces[holder]++, "INVALID_NONCE");
        require(_balances[holder] >= amount, "INSUFFICIENT_BALANCE");

        _withdraw(holder, amount);
    }

    /**
     * @dev Meta approval for max funds.
     * @param holder The holder of the WETH that wishes to approve another account.
     * @param spender The designated spender of the WETH.
     * @param nonce The current permit nonce for this holder, to prevent replays of the increased allowance.
     * @param expiry The time after which this meta approval is not valid.
     * @param allowed true if this spender should be allowed to spend all funds on behalf of the holder, false otherwise.
     * @param v v parameter in the ECDSA signature.
     * @param r r parameter in the ECDSA signature.
     * @param s s parameter in the ECDSA signature.
     */
    function permit(
        address holder,
        address spender,
        uint256 nonce,
        uint256 expiry,
        bool allowed,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                EIP712_DOMAIN_SEPARATOR,
                keccak256(
                    abi.encode(
                        EIP712_PERMIT_TYPEHASH,
                        holder,
                        spender,
                        nonce,
                        expiry,
                        allowed
                    )
                )
            )
        );

        require(holder != address(0), "INVALID_HOLDER");
        require(holder == ecrecover(digest, v, r, s), "INVALID_SIGNATURE");
        require(expiry == 0 || now <= expiry, "PERMIT_EXPIRED");
        require(nonce == permitNonces[holder]++, "INVALID_NONCE");
        uint256 wad = allowed ? uint256(-1) : 0;
        _allowed[holder][spender] = wad;
        emit Approval(holder, spender, wad);
    }

    /**
     * @dev Total number of tokens in existence
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev Gets the balance of the specified address.
     * @param owner The address to query the balance of.
     * @return An uint256 representing the amount owned by the passed address.
     */
    function balanceOf(address owner) public view returns (uint256) {
        return _balances[owner];
    }

    /**
     * @dev Function to check the amount of tokens that an owner allowed to a spender.
     * @param owner address The address which owns the funds.
     * @param spender address The address which will spend the funds.
     * @return A uint256 specifying the amount of tokens still available for the spender.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowed[owner][spender];
    }

    /**
     * @dev Transfer token for a specified address
     * @param to The address to transfer to.
     * @param value The amount to be transferred.
     */
    function transfer(address to, uint256 value) public returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }

    /**
     * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
     * Beware that changing an allowance with this method brings the risk that someone may use both the old
     * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
     * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     */
    function approve(address spender, uint256 value) public returns (bool) {
        require(spender != address(0), "SPENDER_INVALID");

        _allowed[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
    }

    /**
     * @dev Transfer tokens from one address to another.
     * Note that while this function emits an Approval event, this is not required as per the specification,
     * and other compliant implementations may not emit the event.
     * @param from address The address which you want to send tokens from
     * @param to address The address which you want to transfer to
     * @param value uint256 the amount of tokens to be transferred
     */
    function transferFrom(address from, address to, uint256 value) public returns (bool) {
        _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
        _transfer(from, to, value);
        emit Approval(from, msg.sender, _allowed[from][msg.sender]);
        return true;
    }

    /**
     * @dev Increase the amount of tokens that an owner allowed to a spender.
     * approve should be called when allowed_[_spender] == 0. To increment
     * allowed value is better to use this function to avoid 2 calls (and wait until
     * the first transaction is mined)
     * From MonolithDAO Token.sol
     * Emits an Approval event.
     * @param spender The address which will spend the funds.
     * @param addedValue The amount of tokens to increase the allowance by.
     */
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        require(spender != address(0), "SPENDER_INVALID");

        _allowed[msg.sender][spender] = _allowed[msg.sender][spender].add(addedValue);
        emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
        return true;
    }

    /**
     * @dev Decrease the amount of tokens that an owner allowed to a spender.
     * approve should be called when allowed_[_spender] == 0. To decrement
     * allowed value is better to use this function to avoid 2 calls (and wait until
     * the first transaction is mined)
     * From MonolithDAO Token.sol
     * Emits an Approval event.
     * @param spender The address which will spend the funds.
     * @param subtractedValue The amount of tokens to decrease the allowance by.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        require(spender != address(0), "SPENDER_INVALID");

        _allowed[msg.sender][spender] = _allowed[msg.sender][spender].sub(subtractedValue);
        emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
        return true;
    }

    /**
     * @dev Unwraps ETH - exchanges this token, WETH, for ETH 1 to 1
     * @param amount The amount of token to withdraw.
     */
    function withdraw(uint256 amount) public {
        require(_balances[msg.sender] >= amount, "INSUFFICIENT_BALANCE");
        _withdraw(msg.sender, amount);
    }

    /**
     * @dev Transfer token for a specified addresses
     * @param from The address to transfer from.
     * @param to The address to transfer to.
     * @param value The amount to be transferred.
     */
    function _transfer(address from, address to, uint256 value) private {
        require(to != address(0), "SPENDER_INVALID");

        _balances[from] = _balances[from].sub(value);
        _balances[to] = _balances[to].add(value);
        emit Transfer(from, to, value);
    }

    /**
     * @dev Internal function that unwraps ETH - exchanges this token, WETH, for ETH 1 to 1.
     * @param holder The holder that wishes to withdraw to ETH.
     * @param amount The amount of token to withdraw.
     */
    function _withdraw(address payable holder, uint256 amount) private {
        _balances[holder] = _balances[holder].sub(amount);
        holder.transfer(amount);
        emit Withdrawal(holder, amount);
    }

    /**
     * @dev Wraps ETH - exchanges ETH for this token, WETH, 1 to 1
     * Additionally auto approves the defaultOperator for this token to the max amount if it is zero.
     */
    function _deposit(address sender, uint256 amount) private {
        _balances[sender] = _balances[sender].add(amount);
        uint256 senderAllowance = _allowed[sender][defaultOperator];
        if (senderAllowance == 0) {
            _allowed[sender][defaultOperator] = uint256(-1);
        }
        emit Deposit(sender, amount);
    }
}

File 16 of 44 : BaseFillOrder.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../libraries/LibOrder.sol";
import "../../libraries/LibOrderAmounts.sol";
import "../../libraries/LibOutcome.sol";
import "../../interfaces/IEscrow.sol";
import "../../interfaces/IOutcomeReporter.sol";
import "../../interfaces/permissions/ISuperAdminRole.sol";
import "../../interfaces/trading/ITokenTransferProxy.sol";
import "../../interfaces/trading/IFills.sol";
import "../Initializable.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";


/// @title BaseFillOrder
/// @author Julian Wilson <[email protected]>
/// @notice Manages the core internal functionality to fill orders and check their validity.
contract BaseFillOrder is Initializable {
    using LibOrder for LibOrder.Order;
    using SafeMath for uint256;

    ITokenTransferProxy internal proxy;
    IFills internal fills;
    IEscrow internal escrow;
    ISuperAdminRole internal superAdminRole;
    IOutcomeReporter internal outcomeReporter;

    event OrderFill(
        address indexed maker,
        bytes32 indexed marketHash,
        address indexed taker,
        uint256 newFilledAmount,
        bytes32 orderHash,
        bytes32 fillHash,
        LibOrder.Order order,
        LibOrderAmounts.OrderAmounts orderAmounts
    );

    constructor(ISuperAdminRole _superAdminRole) public Initializable() {
        superAdminRole = _superAdminRole;
    }

    /// @notice Initializes this contract with reference to other contracts.
    /// @param _fills The Fills contract.
    /// @param _escrow  The Escrow contract.
    /// @param _tokenTransferProxy The TokenTransferProxy contract.
    function initialize(
        IFills _fills,
        IEscrow _escrow,
        ITokenTransferProxy _tokenTransferProxy,
        IOutcomeReporter _outcomeReporter
    )
        external
        notInitialized
        onlySuperAdmin(msg.sender)
    {
        fills = _fills;
        escrow = _escrow;
        proxy = _tokenTransferProxy;
        outcomeReporter = _outcomeReporter;
        initialized = true;
    }

    /// @notice Throws if the caller is not a super admin.
    /// @param operator The caller of the method.
    modifier onlySuperAdmin(address operator) {
        require(
            superAdminRole.isSuperAdmin(operator),
            "NOT_A_SUPER_ADMIN"
        );
        _;
    }

    /// @notice Intermediate function to fill a single order
    /// @param order The order to be filled.
    /// @param takerAmount The amount to fill the order by.
    /// @param taker The taker of this order.
    /// @param fillHash The fill hash, if applicable.
    function _fillSingleOrder(
        LibOrder.Order memory order,
        uint256 takerAmount,
        address taker,
        bytes32 fillHash
    )
        internal
    {
        LibOrderAmounts.OrderAmounts memory orderAmounts = LibOrderAmounts.computeOrderAmounts(
            order,
            takerAmount
        );

        updateOrderState(
            order,
            orderAmounts,
            taker,
            fillHash
        );
    }

    /// @notice Intermediate function that settles the order for each maker and taker.
    /// @param order The order that is being filled.
    /// @param orderAmounts The resulting order amounts given the taker amount.
    /// @param taker The taker of this order.
    /// @param fillHash The fill hash, if applicable in the case of a meta fill.
    function updateOrderState(
        LibOrder.Order memory order,
        LibOrderAmounts.OrderAmounts memory orderAmounts,
        address taker,
        bytes32 fillHash
    )
        internal
    {
        uint256 newFillAmount = fills.fill(order, orderAmounts.takerAmount);

        settleOrderForMaker(
            order,
            orderAmounts
        );

        settleOrderForTaker(
            order,
            orderAmounts,
            taker
        );

        emit OrderFill(
            order.maker,
            order.marketHash,
            taker,
            newFillAmount,
            order.getOrderHash(),
            fillHash,
            order,
            orderAmounts
        );
    }

    /// @notice Intermediate function that settles the order for the maker.
    /// @param order The order that is being filled.
    /// @param orderAmounts The resulting order amounts given the taker amount.
    function settleOrderForMaker(
        LibOrder.Order memory order,
        LibOrderAmounts.OrderAmounts memory orderAmounts
    )
        internal
    {
        updateMakerEligibility(
            order,
            orderAmounts
        );

        settleTransfersForMaker(
            order,
            orderAmounts
        );
    }

    /// @notice Intermediate function that settles the order for the taker.
    /// @param order The order that is being filled.
    /// @param orderAmounts The resulting order amounts given the taker amount.
    /// @param taker The taker for this order.
    function settleOrderForTaker(
        LibOrder.Order memory order,
        LibOrderAmounts.OrderAmounts memory orderAmounts,
        address taker
    )
        internal
    {
        updateTakerEligibility(
            order,
            orderAmounts,
            taker
        );

        settleTransfersForTaker(
            order,
            orderAmounts,
            taker
        );
    }

    /// @notice Checks that the order is valid given the taker and taker amount.
    /// @param order The order to check.
    /// @param takerAmount The amount the order will be filled by.
    /// @param taker The taker who would fill this order.
    /// @param makerSig The maker signature for this order.
    function assertOrderValid(
        LibOrder.Order memory order,
        uint256 takerAmount,
        address taker,
        bytes memory makerSig
    )
        internal
        view
    {
        require(
            takerAmount > 0,
            "TAKER_AMOUNT_NOT_POSITIVE"
        );
        order.assertValidAsTaker(taker, makerSig);
        require(
            outcomeReporter.getReportTime(order.marketHash) == 0,
            "MARKET_NOT_TRADEABLE"
        );
        require(
            fills.orderHasSpace(order, takerAmount),
            "INSUFFICIENT_SPACE"
        );
    }

    /// @notice Transfers a token using TokenTransferProxy transferFrom function.
    /// @param token Address of token to transferFrom.
    /// @param from Address transfering token.
    /// @param to Address receiving token.
    /// @param value Amount of token to transfer.
    /// @return Success of token transfer.
    function transferViaProxy(
        address token,
        address from,
        address to,
        uint256 value
    )
        internal
        returns (bool)
    {
        return proxy.transferFrom(token, from, to, value);
    }

    /// @notice Updates the taker's eligibility for if they win the bet or tie.
    /// @param order The order that is being filled.
    /// @param orderAmounts The order amounts for this order.
    /// @param taker The taker of this order.
    function updateTakerEligibility(
        LibOrder.Order memory order,
        LibOrderAmounts.OrderAmounts memory orderAmounts,
        address taker
    )
        private
    {
        if (order.isMakerBettingOutcomeOne) {
            escrow.increaseReturnAmount(
                order.marketHash,
                order.baseToken,
                taker,
                LibOutcome.Outcome.OUTCOME_TWO,
                orderAmounts.potSize
            );
            escrow.updateStakedAmount(
                order.marketHash,
                order.baseToken,
                taker,
                LibOutcome.Outcome.OUTCOME_TWO,
                orderAmounts.takerEscrow
            );
        } else {
            escrow.increaseReturnAmount(
                order.marketHash,
                order.baseToken,
                taker,
                LibOutcome.Outcome.OUTCOME_ONE,
                orderAmounts.potSize
            );
            escrow.updateStakedAmount(
                order.marketHash,
                order.baseToken,
                taker,
                LibOutcome.Outcome.OUTCOME_ONE,
                orderAmounts.takerEscrow
            );
        }
    }

    /// @notice Updates the maker's eligibility for if they win the bet or tie.
    /// @param order The order that is being filled.
    /// @param orderAmounts The order amounts for this order.
    function updateMakerEligibility(
        LibOrder.Order memory order,
        LibOrderAmounts.OrderAmounts memory orderAmounts
    )
        private
    {
        if (order.isMakerBettingOutcomeOne) {
            escrow.increaseReturnAmount(
                order.marketHash,
                order.baseToken,
                order.maker,
                LibOutcome.Outcome.OUTCOME_ONE,
                orderAmounts.potSize
            );
            escrow.updateStakedAmount(
                order.marketHash,
                order.baseToken,
                order.maker,
                LibOutcome.Outcome.OUTCOME_ONE,
                orderAmounts.takerAmount
            );
        } else {
            escrow.increaseReturnAmount(
                order.marketHash,
                order.baseToken,
                order.maker,
                LibOutcome.Outcome.OUTCOME_TWO,
                orderAmounts.potSize
            );
            escrow.updateStakedAmount(
                order.marketHash,
                order.baseToken,
                order.maker,
                LibOutcome.Outcome.OUTCOME_TWO,
                orderAmounts.takerAmount
            );
        }
    }

    /// @notice Settles base tokens (not buyer and seller tokens) for the maker.
    /// @param order The order to settle.
    /// @param orderAmounts The resulting order amounts given the taker amount and parameters.
    function settleTransfersForMaker(
        LibOrder.Order memory order,
        LibOrderAmounts.OrderAmounts memory orderAmounts
    )
        private
    {
        require(
            transferViaProxy(
                order.baseToken,
                order.maker,
                address(escrow),
                orderAmounts.takerAmount
            ),
            "CANNOT_TRANSFER_TAKER_ESCROW"
        );
    }

    /// @notice Settles base tokens (not buyer and seller tokens) for the taker.
    /// @param order The order to settle.
    /// @param orderAmounts The resulting order amounts given the taker amount and parameters.
    /// @param taker The taker of this order.
    function settleTransfersForTaker(
        LibOrder.Order memory order,
        LibOrderAmounts.OrderAmounts memory orderAmounts,
        address taker
    )
        private
    {
        require(
            transferViaProxy(
                order.baseToken,
                taker,
                address(escrow),
                orderAmounts.takerEscrow
            ),
            "CANNOT_TRANSFER_TAKER_ESCROW"
        );
    }
}

File 17 of 44 : CancelOrder.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../libraries/LibOrder.sol";
import "../../interfaces/permissions/ISuperAdminRole.sol";
import "../../interfaces/trading/IFills.sol";
import "../../interfaces/trading/ICancelOrder.sol";
import "../Initializable.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";


/// @title CancelOrder
/// @author Julian Wilson <[email protected]>
/// @notice Manages functionality to cancel orders
contract CancelOrder is ICancelOrder, Initializable {
    using LibOrder for LibOrder.Order;
    using SafeMath for uint256;

    ISuperAdminRole private superAdminRole;
    IFills private fills;

    event OrderCancel(
        address indexed maker,
        bytes32 orderHash,
        LibOrder.Order order
    );

    constructor(ISuperAdminRole _superAdminRole) public Initializable() {
        superAdminRole = _superAdminRole;
    }

    /// @notice Throws if the caller is not a super admin.
    /// @param operator The caller of the method.
    modifier onlySuperAdmin(address operator) {
        require(
            superAdminRole.isSuperAdmin(operator),
            "NOT_A_SUPER_ADMIN"
        );
        _;
    }

    /// @notice Initializes this contract with reference to other contracts
    ///         in the protocol.
    /// @param _fills The Fills contract.
    function initialize(IFills _fills)
        external
        notInitialized
        onlySuperAdmin(msg.sender)
    {
        fills = _fills;
        initialized = true;
    }

    /// @notice Cancels an order and prevents and further filling.
    ///         Uses the order hash to uniquely ID the order.
    /// @param order The order to cancel.
    function cancelOrder(LibOrder.Order memory order) public {
        assertCancelValid(order, msg.sender);
        fills.cancel(order);

        emit OrderCancel(
            order.maker,
            order.getOrderHash(),
            order
        );
    }

    /// @notice Cancels multiple orders and prevents further filling.
    /// @param makerOrders The orders to cancel.
    function batchCancelOrders(LibOrder.Order[] memory makerOrders) public {
        uint256 makerOrdersLength = makerOrders.length;
        for (uint256 i = 0; i < makerOrdersLength; i++) {
            cancelOrder(makerOrders[i]);
        }
    }

    /// @notice Checks if a cancel is valid by the canceller.
    /// @param order The order to cancel.
    /// @param canceller The canceller that must be the maker.
    function assertCancelValid(
        LibOrder.Order memory order,
        address canceller
    )
        private
        view
    {
        require(
            order.executor == address(0),
            "EXECUTOR_CANNOT_BE_SET"
        );
        order.assertValidAsMaker(canceller);
        require(
            fills.remainingSpace(order) > 0,
            "INSUFFICIENT_SPACE"
        );
    }
}

File 18 of 44 : EIP712FillHasher.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../libraries/LibOrder.sol";


contract EIP712FillHasher {

    // EIP191 header for EIP712 prefix
    bytes2 constant private EIP191_HEADER = 0x1901;

    // EIP712 Domain Name value
    string constant private EIP712_DOMAIN_NAME = "SportX";

    // EIP712 Domain Version value
    string constant private EIP712_DOMAIN_VERSION = "1.0";

    // EIP712 typeHash of EIP712Domain
    bytes32 constant private EIP712_DOMAIN_SCHEMA_HASH = keccak256(
        abi.encodePacked(
            "EIP712Domain(",
            "string name,",
            "string version,",
            "uint256 chainId,",
            "address verifyingContract",
            ")"
        )
    );

    // EIP712 encodeType of Details
    bytes constant private EIP712_DETAILS_STRING = abi.encodePacked(
        "Details(",
        "string action,",
        "string market,",
        "string betting,",
        "string stake,",
        "string odds,",
        "string returning,",
        "FillObject fills",
        ")"
    );

    // EIP712 encodeType of FillObject
    bytes constant private EIP712_FILL_OBJECT_STRING = abi.encodePacked(
        "FillObject(",
        "Order[] orders,",
        "bytes[] makerSigs,",
        "uint256[] takerAmounts,",
        "uint256 fillSalt",
        ")"
    );

    // EIP712 encodeType of Order
    bytes constant private EIP712_ORDER_STRING = abi.encodePacked(
        "Order(",
        "bytes32 marketHash,",
        "address baseToken,",
        "uint256 totalBetSize,",
        "uint256 percentageOdds,",
        "uint256 expiry,",
        "uint256 salt,",
        "address maker,",
        "address executor,",
        "bool isMakerBettingOutcomeOne",
        ")"
    );

    // EIP712 typeHash of Order
    bytes32 constant private EIP712_ORDER_HASH = keccak256(
        abi.encodePacked(
            EIP712_ORDER_STRING
        )
    );

    // EIP712 typeHash of FillObject
    bytes32 constant private EIP712_FILL_OBJECT_HASH = keccak256(
        abi.encodePacked(
            EIP712_FILL_OBJECT_STRING,
            EIP712_ORDER_STRING
        )
    );

    // EIP712 typeHash of FillObjectWithMetadata
    bytes32 constant private EIP712_DETAILS_HASH = keccak256(
        abi.encodePacked(
            EIP712_DETAILS_STRING,
            EIP712_FILL_OBJECT_STRING,
            EIP712_ORDER_STRING
        )
    );

    // solhint-disable var-name-mixedcase
    bytes32 public EIP712_DOMAIN_HASH;

    constructor(uint256 chainId) public {
        EIP712_DOMAIN_HASH = keccak256(
            abi.encode(
                EIP712_DOMAIN_SCHEMA_HASH,
                keccak256(bytes(EIP712_DOMAIN_NAME)),
                keccak256(bytes(EIP712_DOMAIN_VERSION)),
                chainId,
                address(this)
            )
        );
    }

    function getOrderHash(LibOrder.Order memory order)
        public
        pure
        returns (bytes32)
    {
        return keccak256(
            abi.encode(
                EIP712_ORDER_HASH,
                order.marketHash,
                order.baseToken,
                order.totalBetSize,
                order.percentageOdds,
                order.expiry,
                order.salt,
                order.maker,
                order.executor,
                order.isMakerBettingOutcomeOne
            )
        );
    }

    function getOrdersArrayHash(LibOrder.Order[] memory orders)
        public
        pure
        returns (bytes32)
    {
        bytes32[] memory ordersBytes = new bytes32[](orders.length);

        for (uint256 i = 0; i < orders.length; i++) {
            ordersBytes[i] = getOrderHash(orders[i]);
        }
        return keccak256(abi.encodePacked(ordersBytes));
    }

    function getMakerSigsArrayHash(bytes[] memory sigs)
        public
        pure
        returns (bytes32)
    {
        bytes32[] memory sigsBytes = new bytes32[](sigs.length);

        for (uint256 i = 0; i < sigs.length; i++) {
            sigsBytes[i] = keccak256(sigs[i]);
        }

        return keccak256(abi.encodePacked(sigsBytes));
    }

    function getFillObjectHash(LibOrder.FillObject memory fillObject)
        public
        pure
        returns (bytes32)
    {
        return keccak256(
            abi.encode(
                EIP712_FILL_OBJECT_HASH,
                getOrdersArrayHash(fillObject.orders),
                getMakerSigsArrayHash(fillObject.makerSigs),
                keccak256(abi.encodePacked(fillObject.takerAmounts)),
                fillObject.fillSalt
            )
        );
    }

    function getDetailsHash(LibOrder.FillDetails memory details)
        public
        view
        returns (bytes32)
    {
        bytes32 structHash = keccak256(
            abi.encode(
                EIP712_DETAILS_HASH,
                keccak256(bytes(details.action)),
                keccak256(bytes(details.market)),
                keccak256(bytes(details.betting)),
                keccak256(bytes(details.stake)),
                keccak256(bytes(details.odds)),
                keccak256(bytes(details.returning)),
                getFillObjectHash(details.fills)
            )
        );
        return keccak256(
            abi.encodePacked(
                EIP191_HEADER,
                EIP712_DOMAIN_HASH,
                structHash
            )
        );
    }

    function getDomainHash()
        public
        view
        returns (bytes32)
    {
        return EIP712_DOMAIN_HASH;
    }
}

File 19 of 44 : FeeSchedule.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../interfaces/permissions/IWhitelist.sol";
import "../../interfaces/trading/IFeeSchedule.sol";
import "../../libraries/LibOrder.sol";


/// @title FeeSchedule
/// @author Julian Wilson <[email protected]>
/// @notice Stores the oracle fee for each token (which will presumably all be the same)
contract FeeSchedule is IFeeSchedule {

    IWhitelist private systemParamsWhitelist;

    mapping(address => uint256) private oracleFees; // the convention is 10**20 = 100%

    event NewOracleFee(
        address indexed token,
        uint256 feeFrac
    );

    constructor(IWhitelist _systemParamsWhitelist) public {
        systemParamsWhitelist = _systemParamsWhitelist;
    }

    /// @notice Throws if the caller is not a system params admin.
    modifier onlySystemParamsAdmin() {
        require(
            systemParamsWhitelist.getWhitelisted(msg.sender),
            "NOT_SYSTEM_PARAM_ADMIN"
        );
        _;
    }

    /// @notice Throws if the fee is too high.
    modifier underMaxOracleFee(uint256 feeFrac) {
        require(
            feeFrac < LibOrder.getOddsPrecision(),
            "ORACLE_FEE_TOO_HIGH"
        );
        _;
    }

    /// @notice Gets the oracle fee for the given token.
    /// @param token The token of interest.
    /// @return The oracle fee for this token.
    function getOracleFees(address token) public view returns (uint256) {
        return oracleFees[token];
    }

    /// @notice Sets the oracle fee for the given token.
    /// @param token The token to set.
    /// @param feeFrac The numerator of the fee fraction
    function setOracleFee(address token, uint256 feeFrac)
        public
        onlySystemParamsAdmin
        underMaxOracleFee(feeFrac)
    {
        oracleFees[token] = feeFrac;

        emit NewOracleFee(
            token,
            feeFrac
        );
    }
}

File 20 of 44 : Fills.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../libraries/LibOrder.sol";
import "../../interfaces/trading/IFillOrder.sol";
import "../../interfaces/trading/ICancelOrder.sol";
import "../../interfaces/trading/IFills.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";


/// @title Fills
/// @author Julian Wilson <[email protected]>
/// @notice Stores the "fullness" of each order, whose ID
///         is its hash.
contract Fills is IFills {
    using LibOrder for LibOrder.Order;
    using SafeMath for uint256;

    IFillOrder private fillOrder;
    ICancelOrder private cancelOrder;

    mapping(bytes32 => uint256) private filled;
    mapping(bytes32 => bool) private cancelled;
    mapping(bytes32 => bool) private fillHashSubmitted;

    /// @notice Throws if the caller is not the FillOrder contract.
    modifier onlyFillOrder() {
        require(
            msg.sender == address(fillOrder),
            "ONLY_FILL_ORDER"
        );
        _;
    }

    /// @notice Throws if the caller is not the CancelOrder contract.
    modifier onlyCancelOrderContract() {
        require(
            msg.sender == address(cancelOrder),
            "ONLY_CANCEL_ORDER_CONTRACT"
        );
        _;
    }

    constructor(IFillOrder _fillOrder, ICancelOrder _cancelOrder) public {
        fillOrder = _fillOrder;
        cancelOrder = _cancelOrder;
    }

    /// @notice Fill an order by the given amount.
    /// @param order The order to fill.
    /// @param amount The amount to fill it by.
    /// @return The new filled amount for this order.
    function fill(
        LibOrder.Order memory order,
        uint256 amount
    )
        public
        onlyFillOrder
        returns (uint256)
    {
        bytes32 orderHash = order.getOrderHash();
        filled[orderHash] = filled[orderHash].add(amount);
        return filled[orderHash];
    }

    /// @notice Cancels an order.
    /// @param order The order to cancel.
    function cancel(LibOrder.Order memory order)
        public
        onlyCancelOrderContract
    {
        bytes32 orderHash = order.getOrderHash();
        cancelled[orderHash] = true;
    }

    function setFillHashSubmitted(bytes32 fillHash)
        public
        onlyFillOrder
    {
        fillHashSubmitted[fillHash] = true;
    }

    function getFilled(bytes32 orderHash) public view returns (uint256) {
        return filled[orderHash];
    }

    function getCancelled(bytes32 orderHash) public view returns (bool) {
        return cancelled[orderHash];
    }

    function getFillHashSubmitted(bytes32 orderHash) public view returns (bool) {
        return fillHashSubmitted[orderHash];
    }

    /// @notice Check if an order has sufficient space.
    /// @param order The order to examine.
    /// @param takerAmount The amount to fill.
    /// @return true if there is enough space, false otherwise.
    function orderHasSpace(
        LibOrder.Order memory order,
        uint256 takerAmount
    )
        public
        view
        returns (bool)
    {
        return takerAmount <= remainingSpace(order);
    }

    /// @notice Gets the remaining space for an order.
    /// @param order The order to check.
    /// @return The remaining space on the order. It returns 0 if
    ///         the order is cancelled.
    function remainingSpace(LibOrder.Order memory order)
        public
        view
        returns (uint256)
    {
        bytes32 orderHash = order.getOrderHash();
        if (cancelled[orderHash]) {
            return 0;
        } else {
            return order.totalBetSize.sub(filled[orderHash]);
        }
    }

    /// @notice Checks if the order is cancelled.
    /// @param order The order to check.
    /// @return true if the order is cancelled, false otherwise.
    function isOrderCancelled(LibOrder.Order memory order)
        public
        view
        returns(bool)
    {
        bytes32 orderHash = order.getOrderHash();
        return cancelled[orderHash];
    }
}

File 21 of 44 : TokenTransferProxy.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../interfaces/trading/IFillOrder.sol";
import "../../interfaces/trading/ITokenTransferProxy.sol";
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";


/// @title TokenTransferProxy
/// @author Julian Wilson <[email protected]>
/// @notice Transfers tokens on behalf of the user.
contract TokenTransferProxy is ITokenTransferProxy {

    IFillOrder private fillOrder;

    constructor (IFillOrder _fillOrder) public {
        fillOrder = _fillOrder;
    }

    /// @notice Throws if the caller is not a fill order contract derivative
    modifier onlyFillOrder() {
        require(
            msg.sender == address(fillOrder),
            "ONLY_FILL_ORDER"
        );
        _;
    }

    /// @notice Uses `transferFrom` and ERC20 approval to transfer tokens.
    ///         Only callable by whitelisted addresses.
    /// @param token The address of the ERC20 token to transfer on the user's behalf.
    /// @param from The address of the user.
    /// @param to The destination address.
    /// @param value The amount to transfer.
    function transferFrom(
        address token,
        address from,
        address to,
        uint256 value
    )
        public
        onlyFillOrder
        returns (bool)
    {
        return IERC20(token).transferFrom(from, to, value);
    }
}

File 22 of 44 : IAffiliateRegistry.sol
pragma solidity 0.5.16;

contract IAffiliateRegistry {
    function setAffiliate(address member, address affiliate) public;
    function setAffiliateFeeFrac(address affiliate, uint256 fee) public;
    function setDefaultAffiliate(address affiliate) public;
    function getAffiliate(address member) public view returns (address);
    function getAffiliateFeeFrac(address affiliate) public view returns (uint256);
    function getDefaultAffiliate() public view returns (address);
}

File 23 of 44 : IEscrow.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../libraries/LibOutcome.sol";


contract IEscrow {
    struct Eligibility {
        bool hasEligibility;
        LibOutcome.Outcome outcome;
        uint256 amount;
    }

    function getReturnAmount(bytes32, address, address, LibOutcome.Outcome) public view returns (uint256);
    function getStakedAmount(bytes32, address, address, LibOutcome.Outcome) public view returns (uint256);
    function settleBet(address, bytes32, address) public;
    function updateStakedAmount(bytes32, address, address, LibOutcome.Outcome, uint256) public;
    function increaseReturnAmount(bytes32, address, address, LibOutcome.Outcome, uint256) public;
    function isMarketRedeemable(bytes32) public view returns (bool);
    function getEligibility(address, bytes32, address) public view returns (Eligibility memory);
}

File 24 of 44 : IOutcomeReporter.sol
pragma solidity 0.5.16;

import "../libraries/LibOutcome.sol";
contract IOutcomeReporter {
    function getReportedOutcome(bytes32)
        public
        view
        returns (LibOutcome.Outcome);
    function getReportTime(bytes32) public view returns (uint256);
    function reportOutcome(bytes32, LibOutcome.Outcome) public;
    function reportOutcomes(bytes32[] memory, LibOutcome.Outcome[] memory)
        public;
}

File 25 of 44 : ISystemParameters.sol
pragma solidity 0.5.16;

contract ISystemParameters {
    function getOracleFeeRecipient() public view returns (address);
    function setNewOracleFeeRecipient(address) public;
}

File 26 of 44 : IOrderValidator.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../libraries/LibOrder.sol";
contract IOrderValidator {
    function getOrderStatus(LibOrder.Order memory, bytes memory)
        public
        view
        returns (string memory);

    function getMultiOrderStatus(LibOrder.Order[] memory, bytes[] memory)
        public
        view
        returns (string[] memory);

    function getFillStatus(LibOrder.FillDetails memory, bytes memory, address)
        public
        view
        returns (string memory);

    function getMetaFillStatus(
        LibOrder.FillDetails memory,
        address,
        bytes memory,
        bytes memory)
        public view returns (string memory);
}

File 27 of 44 : ISuperAdminRole.sol
pragma solidity 0.5.16;

contract ISuperAdminRole {
    function isSuperAdmin(address account) public view returns (bool);
    function addSuperAdmin(address account) public;
    function removeSuperAdmin(address account) public;
    function getSuperAdminCount() public view returns (uint256);
}

File 28 of 44 : IWhitelist.sol
pragma solidity 0.5.16;

contract IWhitelist {
    function addAddressToWhitelist(address) public;
    function removeAddressFromWhitelist(address) public;
    function getWhitelisted(address) public view returns (bool);
}

File 29 of 44 : IDetailedTokenDAI.sol
pragma solidity 0.5.16;

contract IDetailedTokenDAI {
    function name() public view returns (bytes32);
    function symbol() public view returns (bytes32);
    function decimals() public view returns (uint256);
}

File 30 of 44 : ICancelOrder.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../libraries/LibOrder.sol";

contract ICancelOrder {
    function cancelOrder(LibOrder.Order memory order) public;
    function batchCancelOrders(LibOrder.Order[] memory makerOrders) public;
}

File 31 of 44 : IEIP712FillHasher.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../libraries/LibOrder.sol";

contract IEIP712FillHasher {
    function getOrderHash(LibOrder.Order memory) public  pure returns (bytes32);
    function getOrdersArrayHash(LibOrder.Order[] memory) public  pure returns (bytes32);
    function getMakerSigsArrayHash(bytes[] memory) public  pure returns (bytes32);
    function getTakerAmountsArrayHash(uint256[] memory) public  pure returns (bytes32);
    function getFillObjectHash(LibOrder.FillObject memory) public  pure returns (bytes32);
    function getDetailsHash(LibOrder.FillDetails memory) public  view returns (bytes32);
    function getDomainHash() public  view returns (bytes32);
}

File 32 of 44 : IFeeSchedule.sol
pragma solidity 0.5.16;

contract IFeeSchedule {
    function getOracleFees(address) public view returns (uint256);
    function setOracleFee(address, uint256) public;
}

File 33 of 44 : IFillOrder.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../libraries/LibOrder.sol";

contract IFillOrder {
    function fillOrders(LibOrder.FillDetails memory, bytes memory) public;
    function metaFillOrders(
        LibOrder.FillDetails memory,
        address,
        bytes memory,
        bytes memory)
        public;
}

File 34 of 44 : IFills.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../libraries/LibOrder.sol";

contract IFills {
    function getFilled(bytes32) public view returns (uint256);
    function getCancelled(bytes32) public view returns (bool);
    function getFillHashSubmitted(bytes32) public view returns (bool);
    function orderHasSpace(LibOrder.Order memory, uint256)
        public
        view
        returns (bool);
    function remainingSpace(LibOrder.Order memory)
        public
        view
        returns (uint256);
    function isOrderCancelled(LibOrder.Order memory) public view returns (bool);
    function fill(LibOrder.Order memory, uint256) public returns (uint256);
    function cancel(LibOrder.Order memory) public;
    function setFillHashSubmitted(bytes32) public;
}

File 35 of 44 : IReadOnlyValidator.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "../../libraries/LibOrder.sol";

contract IReadOnlyValidator {
    function getOrderStatus(LibOrder.Order memory, bytes memory)
        public
        view
        returns (string memory);
    function getOrderStatusForTaker(
        LibOrder.Order memory,
        address,
        uint256,
        bytes memory)
        public view returns (string memory);
    function getCumulativeOrderStatusForTaker(
        LibOrder.Order[] memory,
        address,
        uint256[] memory,
        bytes[] memory)
        public view returns (string memory);
}

File 36 of 44 : ITokenTransferProxy.sol
pragma solidity 0.5.16;

contract ITokenTransferProxy {
    function transferFrom(address, address, address, uint256)
        public
        returns (bool);
}

File 37 of 44 : LibOrder.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/cryptography/ECDSA.sol";


/// @title LibOrder
/// @author Julian Wilson <[email protected]>
/// @notice Central definition for what an "order" is along with utilities for an order.
library LibOrder {
    using SafeMath for uint256;

    uint256 public constant ODDS_PRECISION = 10**20;

    struct Order {
        bytes32 marketHash;
        address baseToken;
        uint256 totalBetSize;
        uint256 percentageOdds;
        uint256 expiry;
        uint256 salt;
        address maker;
        address executor;
        bool isMakerBettingOutcomeOne;
    }

    struct FillObject {
        Order[] orders;
        bytes[] makerSigs;
        uint256[] takerAmounts;
        uint256 fillSalt;
    }

    struct FillDetails {
        string action;
        string market;
        string betting;
        string stake;
        string odds;
        string returning;
        FillObject fills;
    }

    /// @notice Checks the parameters of the given order to see if it conforms to the protocol.
    /// @param order The order to check.
    /// @return A status string in UPPER_SNAKE_CASE. It will return "OK" if everything checks out.
    // solhint-disable code-complexity
    function getParamValidity(Order memory order)
        internal
        view
        returns (string memory)
    {
        if (order.totalBetSize == 0) {return "TOTAL_BET_SIZE_ZERO";}
        if (order.percentageOdds == 0 || order.percentageOdds >= ODDS_PRECISION) {return "INVALID_PERCENTAGE_ODDS";}
        if (order.expiry < now) {return "ORDER_EXPIRED";}
        if (order.baseToken == address(0)) {return "BASE_TOKEN";}
        return "OK";
    }

    /// @notice Checks the signature of an order to see if
    ///         it was an order signed by the given maker.
    /// @param order The order to check.
    /// @param makerSig The signature to compare.
    /// @return true if the signature matches, false otherwise.
    function checkSignature(Order memory order, bytes memory makerSig)
        internal
        pure
        returns (bool)
    {
        bytes32 orderHash = getOrderHash(order);
        return ECDSA.recover(ECDSA.toEthSignedMessageHash(orderHash), makerSig) == order.maker;
    }

    /// @notice Checks if an order's parameters conforms to the protocol's specifications.
    /// @param order The order to check.
    function assertValidParams(Order memory order) internal view {
        require(
            order.totalBetSize > 0,
            "TOTAL_BET_SIZE_ZERO"
        );
        require(
            order.percentageOdds > 0 && order.percentageOdds < ODDS_PRECISION,
            "INVALID_PERCENTAGE_ODDS"
        );
        require(order.baseToken != address(0), "INVALID_BASE_TOKEN");
        require(order.expiry > now, "ORDER_EXPIRED");
    }

    /// @notice Checks if an order has valid parameters including
    ///         the signature and checks if the maker is not the taker.
    /// @param order The order to check.
    /// @param taker The hypothetical filler of this order, i.e., the taker.
    /// @param makerSig The signature to check.
    function assertValidAsTaker(Order memory order, address taker, bytes memory makerSig) internal view {
        assertValidParams(order);
        require(
            checkSignature(order, makerSig),
            "SIGNATURE_MISMATCH"
        );
        require(order.maker != taker, "TAKER_NOT_MAKER");
    }

    /// @notice Checks if the order has valid parameters
    ///         and checks if the sender is the maker.
    /// @param order The order to check.
    /// @param sender The address to compare the maker to.
    function assertValidAsMaker(Order memory order, address sender) internal view {
        assertValidParams(order);
        require(order.maker == sender, "CALLER_NOT_MAKER");
    }

    /// @notice Computes the hash of an order. Packs the arguments in order
    ///         of the Order struct.
    /// @param order The order to compute the hash of.
    function getOrderHash(Order memory order) internal pure returns (bytes32) {
        return keccak256(
            abi.encodePacked(
                order.marketHash,
                order.baseToken,
                order.totalBetSize,
                order.percentageOdds,
                order.expiry,
                order.salt,
                order.maker,
                order.executor,
                order.isMakerBettingOutcomeOne
            )
        );
    }

    function getOddsPrecision() internal pure returns (uint256) {
        return ODDS_PRECISION;
    }
}

File 38 of 44 : LibOrderAmounts.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;

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


/// @title LibOrderAmounts
/// @author Julian Wilson <[email protected]>
/// @notice Struct definition for the resulting individual computed amounts
///         when filling an order.
library LibOrderAmounts {
    using SafeMath for uint256;

    struct OrderAmounts {
        uint256 takerAmount;
        uint256 takerEscrow;
        uint256 potSize;
    }

    /// @notice Computes the tokens that should be transferred as a result of
    ///         the order and the specified fill amount.
    /// @param order The reference maker order
    /// @param takerAmount The amount to fill of this order.
    /// @return An OrderAmounts struct.
    function computeOrderAmounts(
        LibOrder.Order memory order,
        uint256 takerAmount
    )
        internal
        pure
        returns (LibOrderAmounts.OrderAmounts memory)
    {
        uint256 oddsPrecision = LibOrder.getOddsPrecision();
        uint256 potSize = takerAmount.mul(oddsPrecision).div(order.percentageOdds);
        uint256 takerEscrow = potSize.sub(takerAmount);

        return LibOrderAmounts.OrderAmounts({
            takerAmount: takerAmount,
            takerEscrow: takerEscrow,
            potSize: potSize
        });
    }

    /// @notice Combines two OrderAmounts into one by adding up
    ///         the values
    /// @param orderAmount1 The first OrderAmount
    /// @param orderAmount2 The second OrderAmount
    /// @return The combined OrderAmounts struct.
    function reduceOrderAmounts(
        LibOrderAmounts.OrderAmounts memory orderAmount1,
        LibOrderAmounts.OrderAmounts memory orderAmount2
    )
        internal
        pure
        returns (LibOrderAmounts.OrderAmounts memory)
    {
        return LibOrderAmounts.OrderAmounts({
            takerAmount: orderAmount1.takerAmount.add(orderAmount2.takerAmount),
            takerEscrow: orderAmount1.takerEscrow.add(orderAmount2.takerEscrow),
            potSize: orderAmount1.potSize.add(orderAmount2.potSize)
        });
    }

    /// @notice Takes a bunch of orders and taker amounts
    ///         and computes the total order amounts
    /// @param makerOrders The reference maker orders
    /// @param takerAmounts An array of taker amounts, one for each order
    /// @return The total OrderAmounts struct.
    function computeTotalOrderAmounts(
        LibOrder.Order[] memory makerOrders,
        uint256[] memory takerAmounts
    )
        internal
        pure
        returns (LibOrderAmounts.OrderAmounts memory)
    {
        LibOrderAmounts.OrderAmounts memory combinedOrderAmounts;
        uint256 makerOrdersLength = makerOrders.length;
        for (uint256 i = 0; i < makerOrdersLength; i++) {
            LibOrderAmounts.OrderAmounts memory orderAmounts = computeOrderAmounts(
                makerOrders[i],
                takerAmounts[i]
            );
            combinedOrderAmounts = reduceOrderAmounts(combinedOrderAmounts, orderAmounts);
        }
        return combinedOrderAmounts;
    }
}

File 39 of 44 : LibOutcome.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;


/// @title LibOutcome
/// @author Julian Wilson <[email protected]>
/// @notice Enumerations and utilities related to voting.
library LibOutcome {
    enum Outcome { VOID, OUTCOME_ONE, OUTCOME_TWO }
}

File 40 of 44 : LibString.sol
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;


/// @title LibString
/// @author Julian Wilson <[email protected]>
/// @notice Utility to efficiently compare strings when necessary.
library LibString {

    /// @notice Compares two strings by taking their hash.
    /// @param a The first string.
    /// @param b The second string.
    /// @return true or false depending on if the strings matched.
    function equals(string memory a, string memory b)
        internal
        pure
        returns (bool)
    {
        return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b));
    }
}

File 41 of 44 : SafeMath.sol
pragma solidity ^0.5.0;

/**
 * @title SafeMath
 * @dev Unsigned math operations with safety checks that revert on error
 */
library SafeMath {
    /**
    * @dev Multiplies two unsigned integers, reverts on 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);

        return c;
    }

    /**
    * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
    */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
    * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
    */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        uint256 c = a - b;

        return c;
    }

    /**
    * @dev Adds two unsigned integers, reverts on overflow.
    */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);

        return c;
    }

    /**
    * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
    * reverts when dividing by zero.
    */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0);
        return a % b;
    }
}

File 42 of 44 : IERC20.sol
pragma solidity ^0.5.0;

/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
interface IERC20 {
    function transfer(address to, uint256 value) external returns (bool);

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

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

    function totalSupply() external view returns (uint256);

    function balanceOf(address who) external view returns (uint256);

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

    event Transfer(address indexed from, address indexed to, uint256 value);

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

File 43 of 44 : Roles.sol
pragma solidity ^0.5.0;

/**
 * @title Roles
 * @dev Library for managing addresses assigned to a Role.
 */
library Roles {
    struct Role {
        mapping (address => bool) bearer;
    }

    /**
     * @dev give an account access to this role
     */
    function add(Role storage role, address account) internal {
        require(account != address(0));
        require(!has(role, account));

        role.bearer[account] = true;
    }

    /**
     * @dev remove an account's access to this role
     */
    function remove(Role storage role, address account) internal {
        require(account != address(0));
        require(has(role, account));

        role.bearer[account] = false;
    }

    /**
     * @dev check if an account has this role
     * @return bool
     */
    function has(Role storage role, address account) internal view returns (bool) {
        require(account != address(0));
        return role.bearer[account];
    }
}

File 44 of 44 : ECDSA.sol
pragma solidity ^0.5.0;

/**
 * @title Elliptic curve signature operations
 * @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
 * TODO Remove this library once solidity supports passing a signature to ecrecover.
 * See https://github.com/ethereum/solidity/issues/864
 */

library ECDSA {
    /**
     * @dev Recover signer address from a message by using their signature
     * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
     * @param signature bytes signature, the signature is generated using web3.eth.sign()
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        bytes32 r;
        bytes32 s;
        uint8 v;

        // Check the signature length
        if (signature.length != 65) {
            return (address(0));
        }

        // Divide the signature in r, s and v variables
        // ecrecover takes the signature parameters, and the only way to get them
        // currently is to use assembly.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            r := mload(add(signature, 0x20))
            s := mload(add(signature, 0x40))
            v := byte(0, mload(add(signature, 0x60)))
        }

        // Version of signature should be 27 or 28, but 0 and 1 are also possible versions
        if (v < 27) {
            v += 27;
        }

        // If the version is correct return the signer address
        if (v != 27 && v != 28) {
            return (address(0));
        } else {
            return ecrecover(hash, v, r, s);
        }
    }

    /**
     * toEthSignedMessageHash
     * @dev prefix a bytes32 value with "\x19Ethereum Signed Message:"
     * and hash the result
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract ISuperAdminRole","name":"_superAdminRole","type":"address"},{"internalType":"contract IEIP712FillHasher","name":"_eip712FillHasher","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"maker","type":"address"},{"indexed":true,"internalType":"bytes32","name":"marketHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"taker","type":"address"},{"indexed":false,"internalType":"uint256","name":"newFilledAmount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"fillHash","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"marketHash","type":"bytes32"},{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"uint256","name":"totalBetSize","type":"uint256"},{"internalType":"uint256","name":"percentageOdds","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"bool","name":"isMakerBettingOutcomeOne","type":"bool"}],"indexed":false,"internalType":"struct LibOrder.Order","name":"order","type":"tuple"},{"components":[{"internalType":"uint256","name":"takerAmount","type":"uint256"},{"internalType":"uint256","name":"takerEscrow","type":"uint256"},{"internalType":"uint256","name":"potSize","type":"uint256"}],"indexed":false,"internalType":"struct LibOrderAmounts.OrderAmounts","name":"orderAmounts","type":"tuple"}],"name":"OrderFill","type":"event"},{"constant":false,"inputs":[{"components":[{"internalType":"string","name":"action","type":"string"},{"internalType":"string","name":"market","type":"string"},{"internalType":"string","name":"betting","type":"string"},{"internalType":"string","name":"stake","type":"string"},{"internalType":"string","name":"odds","type":"string"},{"internalType":"string","name":"returning","type":"string"},{"components":[{"components":[{"internalType":"bytes32","name":"marketHash","type":"bytes32"},{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"uint256","name":"totalBetSize","type":"uint256"},{"internalType":"uint256","name":"percentageOdds","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"bool","name":"isMakerBettingOutcomeOne","type":"bool"}],"internalType":"struct LibOrder.Order[]","name":"orders","type":"tuple[]"},{"internalType":"bytes[]","name":"makerSigs","type":"bytes[]"},{"internalType":"uint256[]","name":"takerAmounts","type":"uint256[]"},{"internalType":"uint256","name":"fillSalt","type":"uint256"}],"internalType":"struct LibOrder.FillObject","name":"fills","type":"tuple"}],"internalType":"struct LibOrder.FillDetails","name":"fillDetails","type":"tuple"},{"internalType":"bytes","name":"executorSig","type":"bytes"}],"name":"fillOrders","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IFills","name":"_fills","type":"address"},{"internalType":"contract IEscrow","name":"_escrow","type":"address"},{"internalType":"contract ITokenTransferProxy","name":"_tokenTransferProxy","type":"address"},{"internalType":"contract IOutcomeReporter","name":"_outcomeReporter","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"components":[{"internalType":"string","name":"action","type":"string"},{"internalType":"string","name":"market","type":"string"},{"internalType":"string","name":"betting","type":"string"},{"internalType":"string","name":"stake","type":"string"},{"internalType":"string","name":"odds","type":"string"},{"internalType":"string","name":"returning","type":"string"},{"components":[{"components":[{"internalType":"bytes32","name":"marketHash","type":"bytes32"},{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"uint256","name":"totalBetSize","type":"uint256"},{"internalType":"uint256","name":"percentageOdds","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"bool","name":"isMakerBettingOutcomeOne","type":"bool"}],"internalType":"struct LibOrder.Order[]","name":"orders","type":"tuple[]"},{"internalType":"bytes[]","name":"makerSigs","type":"bytes[]"},{"internalType":"uint256[]","name":"takerAmounts","type":"uint256[]"},{"internalType":"uint256","name":"fillSalt","type":"uint256"}],"internalType":"struct LibOrder.FillObject","name":"fills","type":"tuple"}],"internalType":"struct LibOrder.FillDetails","name":"fillDetails","type":"tuple"},{"internalType":"address","name":"taker","type":"address"},{"internalType":"bytes","name":"takerSig","type":"bytes"},{"internalType":"bytes","name":"executorSig","type":"bytes"}],"name":"metaFillOrders","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b50604051620026bf380380620026bf833981016040819052620000349162000066565b600380546001600160a01b039384166001600160a01b03199182161790915560058054929093169116179055620000bd565b6000806040838503121562000079578182fd5b82516200008681620000a4565b60208401519092506200009981620000a4565b809150509250929050565b6001600160a01b0381168114620000ba57600080fd5b50565b6125f280620000cd6000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063158ef93e14610051578063220bfc541461006f5780639a89f58914610084578063f8c8765e14610097575b600080fd5b6100596100aa565b6040516100669190612045565b60405180910390f35b61008261007d366004611d32565b6100b3565b005b610082610092366004611c99565b610393565b6100826100a5366004611c3e565b6106d2565b60005460ff1681565b60008260c00151600001516000815181106100ca57fe5b602002602001015160e00151905060008360c0015160400151518460c001516000015151148015610106575060c0840151602081015151905151145b61012b5760405162461bcd60e51b81526004016101229061219d565b60405180910390fd5b6001600160a01b0382161561036f576005546040516334640aad60e21b81526001600160a01b039091169063d1902ab49061016a90879060040161241a565b60206040518083038186803b15801561018257600080fd5b505afa158015610196573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506101ba9190810190611c26565b600154604051631a5ab2cb60e31b81529192506001600160a01b03169063d2d59658906101eb908490600401612050565b60206040518083038186803b15801561020357600080fd5b505afa158015610217573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061023b9190810190611c0a565b156102585760405162461bcd60e51b815260040161012290612236565b816001600160a01b031661026c82856107f8565b6001600160a01b0316146102925760405162461bcd60e51b8152600401610122906123ac565b60c084015151516001101561030c5760015b60c0850151515181101561030a57826001600160a01b03168560c001516000015182815181106102d057fe5b602002602001015160e001516001600160a01b0316146103025760405162461bcd60e51b815260040161012290612353565b6001016102a4565b505b6001546040516339d63abd60e21b81526001600160a01b039091169063e758eaf49061033c908490600401612050565b600060405180830381600087803b15801561035657600080fd5b505af115801561036a573d6000803e3d6000fd5b505050505b60c08401518051604082015160209092015161038d929033856108b9565b50505050565b6005546040516334640aad60e21b81526000916001600160a01b03169063d1902ab4906103c490889060040161241a565b60206040518083038186803b1580156103dc57600080fd5b505afa1580156103f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104149190810190611c26565b9050836001600160a01b031661042a82856107f8565b6001600160a01b0316146104505760405162461bcd60e51b81526004016101229061229d565b600154604051631a5ab2cb60e31b81526001600160a01b039091169063d2d5965890610480908490600401612050565b60206040518083038186803b15801561049857600080fd5b505afa1580156104ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104d09190810190611c0a565b156104ed5760405162461bcd60e51b815260040161012290612236565b60008560c001516000015160008151811061050457fe5b602002602001015160e00151905060006001600160a01b0316816001600160a01b03161461058e57336001600160a01b038216146105545760405162461bcd60e51b815260040161012290612266565b806001600160a01b031661056883856107f8565b6001600160a01b03161461058e5760405162461bcd60e51b8152600401610122906123ac565b60c08601516040810151519051511480156105b4575060c0860151602081015151905151145b6105d05760405162461bcd60e51b81526004016101229061219d565b60c086015151516001101561064a5760015b60c0870151515181101561064857816001600160a01b03168760c0015160000151828151811061060e57fe5b602002602001015160e001516001600160a01b0316146106405760405162461bcd60e51b815260040161012290612353565b6001016105e2565b505b60c086015180516040820151602090920151610668929088866108b9565b6001546040516339d63abd60e21b81526001600160a01b039091169063e758eaf490610698908590600401612050565b600060405180830381600087803b1580156106b257600080fd5b505af11580156106c6573d6000803e3d6000fd5b50505050505050505050565b60005460ff16156106f55760405162461bcd60e51b815260040161012290612144565b60035460405163df7f453b60e01b815233916001600160a01b03169063df7f453b90610725908490600401612007565b60206040518083038186803b15801561073d57600080fd5b505afa158015610751573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107759190810190611c0a565b6107915760405162461bcd60e51b81526004016101229061220b565b50600180546001600160a01b039586166001600160a01b031991821617825560028054958716958216959095179094556000805460048054948816949096169390931790945560ff199290941661010002610100600160a81b031990911617169091179055565b600080600080845160411461081357600093505050506108b3565b50505060208201516040830151606084015160001a601b81101561083557601b015b8060ff16601b1415801561084d57508060ff16601c14155b1561085e57600093505050506108b3565b600186828585604051600081526020016040526040516108819493929190612094565b6020604051602081039080840390855afa1580156108a3573d6000803e3d6000fd5b5050506020604051035193505050505b92915050565b60006108c786868686610930565b905080156108e0576108db86868585610a9e565b610928565b60005b86518110156109265761091e8782815181106108fb57fe5b602002602001015187838151811061090f57fe5b60200260200101518686610ae4565b6001016108e3565b505b505050505050565b6000808560008151811061094057fe5b60200260200101516101000151905060008660008151811061095e57fe5b602002602001015160000151905060008760008151811061097b57fe5b602002602001015160200151905060008090505b88518110156109e5576109dd8982815181106109a757fe5b60200260200101518983815181106109bb57fe5b6020026020010151888a85815181106109d057fe5b6020026020010151610b04565b60010161098f565b50600188511115610a8e5760015b8851811015610a8c57831515898281518110610a0b57fe5b602002602001015161010001511515141580610a3e575082898281518110610a2f57fe5b60200260200101516000015114155b80610a725750816001600160a01b0316898281518110610a5a57fe5b6020026020010151602001516001600160a01b031614155b15610a84576000945050505050610a96565b6001016109f3565b505b600193505050505b949350505050565b610aa66117d9565b610ab08585610c70565b9050610ad185600081518110610ac257fe5b60200260200101518285610ce6565b610add85858585610d01565b5050505050565b610aec6117d9565b610af68585610eb6565b9050610add85828585610f2b565b60008311610b245760405162461bcd60e51b81526004016101229061210d565b610b3584838363ffffffff61103216565b600480548551604051637d4b2a1960e01b81526001600160a01b0390921692637d4b2a1992610b65929101612050565b60206040518083038186803b158015610b7d57600080fd5b505afa158015610b91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610bb59190810190611c26565b15610bd25760405162461bcd60e51b8152600401610122906120b2565b60015460405163a5f650d760e01b81526001600160a01b039091169063a5f650d790610c0490879087906004016124ed565b60206040518083038186803b158015610c1c57600080fd5b505afa158015610c30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610c549190810190611c0a565b61038d5760405162461bcd60e51b815260040161012290612327565b610c786117d9565b610c806117d9565b835160005b81811015610cdc57610c956117d9565b610cc5878381518110610ca457fe5b6020026020010151878481518110610cb857fe5b6020026020010151610eb6565b9050610cd18482611097565b935050600101610c85565b5090949350505050565b610cf1838383611109565b610cfc8383836112e3565b505050565b60005b8451811015610add57610d156117d9565b610d38868381518110610d2457fe5b6020026020010151868481518110610cb857fe5b60015487519192506000916001600160a01b039091169063c9f67f9c90899086908110610d6157fe5b602002602001015184600001516040518363ffffffff1660e01b8152600401610d8b9291906124ed565b602060405180830381600087803b158015610da557600080fd5b505af1158015610db9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ddd9190810190611c26565b9050610dfc878481518110610dee57fe5b602002602001015183611323565b846001600160a01b0316878481518110610e1257fe5b602002602001015160000151888581518110610e2a57fe5b602002602001015160c001516001600160a01b03167f7fce7b83d2014c90bf64f0281296c1ecf7429a9473167b683f3f14c55bfe9e1f84610e7d8c8981518110610e7057fe5b602002602001015161133b565b898d8a81518110610e8a57fe5b602002602001015189604051610ea495949392919061250a565b60405180910390a45050600101610d04565b610ebe6117d9565b6000610ec8611398565b90506000610ef38560600151610ee784876113a590919063ffffffff16565b9063ffffffff6113d316565b90506000610f07828663ffffffff6113f516565b60408051606081018252968752602087019190915285019190915250919392505050565b600154835160405163327d9fe760e21b81526000926001600160a01b03169163c9f67f9c91610f5e9189916004016124ed565b602060405180830381600087803b158015610f7857600080fd5b505af1158015610f8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610fb09190810190611c26565b9050610fbc8585611323565b610fc7858585610ce6565b826001600160a01b031685600001518660c001516001600160a01b03167f7fce7b83d2014c90bf64f0281296c1ecf7429a9473167b683f3f14c55bfe9e1f8461100f8a61133b565b878b8b60405161102395949392919061250a565b60405180910390a45050505050565b61103b8361140a565b61104583826114ba565b6110615760405162461bcd60e51b815260040161012290612171565b816001600160a01b03168360c001516001600160a01b03161415610cfc5760405162461bcd60e51b815260040161012290612383565b61109f6117d9565b60408051606081019091528251845182916110c0919063ffffffff6114fa16565b81526020016110e0846020015186602001516114fa90919063ffffffff16565b8152602001611100846040015186604001516114fa90919063ffffffff16565b90529392505050565b82610100015115611201576002805484516020860151604080870151905163c6b4931560e01b81526001600160a01b039094169463c6b4931594611154949392889291600401612059565b600060405180830381600087803b15801561116e57600080fd5b505af1158015611182573d6000803e3d6000fd5b50506002805486516020808901519088015160405163904e531b60e01b81526001600160a01b03909416965063904e531b95506111ca94929391928892909190600401612059565b600060405180830381600087803b1580156111e457600080fd5b505af11580156111f8573d6000803e3d6000fd5b50505050610cfc565b60025483516020850151604080860151905163c6b4931560e01b81526001600160a01b039094169363c6b493159361124493909290918791600191600401612059565b600060405180830381600087803b15801561125e57600080fd5b505af1158015611272573d6000803e3d6000fd5b505060025485516020808801519087015160405163904e531b60e01b81526001600160a01b03909416955063904e531b94506112b5938791600191600401612059565b600060405180830381600087803b1580156112cf57600080fd5b505af1158015610926573d6000803e3d6000fd5b602080840151600254918401516113079284916001600160a01b039091169061150c565b610cfc5760405162461bcd60e51b8152600401610122906123e3565b61132d82826115a2565b6113378282611786565b5050565b80516020808301516040808501516060860151608087015160a088015160c089015160e08a01516101008b0151965160009a61137b9a9099989101611f77565b604051602081830303815290604052805190602001209050919050565b68056bc75e2d6310000090565b6000826113b4575060006108b3565b828202828482816113c157fe5b04146113cc57600080fd5b9392505050565b60008082116113e157600080fd5b60008284816113ec57fe5b04949350505050565b60008282111561140457600080fd5b50900390565b600081604001511161142e5760405162461bcd60e51b8152600401610122906120e0565b6000816060015111801561144e575068056bc75e2d631000008160600151105b61146a5760405162461bcd60e51b8152600401610122906121d4565b60208101516001600160a01b03166114945760405162461bcd60e51b8152600401610122906122fb565b428160800151116114b75760405162461bcd60e51b8152600401610122906122d4565b50565b6000806114c68461133b565b90508360c001516001600160a01b03166114e86114e2836117c6565b856107f8565b6001600160a01b031614949350505050565b6000828201838110156113cc57600080fd5b60008054604051630aed65f560e11b81526101009091046001600160a01b0316906315dacbea9061154790889088908890889060040161201b565b602060405180830381600087803b15801561156157600080fd5b505af1158015611575573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115999190810190611c0a565b95945050505050565b8161010001511561169f576002548251602084015160c0850151604080860151905163c6b4931560e01b81526001600160a01b039095169463c6b49315946115f69490939092909160019190600401612059565b600060405180830381600087803b15801561161057600080fd5b505af1158015611624573d6000803e3d6000fd5b50506002548451602086015160c0870151865160405163904e531b60e01b81526001600160a01b03909516965063904e531b95506116689460019190600401612059565b600060405180830381600087803b15801561168257600080fd5b505af1158015611696573d6000803e3d6000fd5b50505050611337565b600280548351602085015160c0860151604080870151905163c6b4931560e01b81526001600160a01b039095169563c6b49315956116e39594939290600401612059565b600060405180830381600087803b1580156116fd57600080fd5b505af1158015611711573d6000803e3d6000fd5b5050600280548551602087015160c0880151875160405163904e531b60e01b81526001600160a01b03909516975063904e531b965061175895939492939192600401612059565b600060405180830381600087803b15801561177257600080fd5b505af1158015610928573d6000803e3d6000fd5b602082015160c083015160025483516117aa9392916001600160a01b03169061150c565b6113375760405162461bcd60e51b8152600401610122906123e3565b60008160405160200161137b9190611fd6565b60405180606001604052806000815260200160008152602001600081525090565b80356108b38161258c565b600082601f830112611815578081fd5b81356118286118238261256c565b612545565b8181529150602080830190840160005b838110156118655761185087602084358901016119d9565b83526020928301929190910190600101611838565b5050505092915050565b600082601f83011261187f578081fd5b813561188d6118238261256c565b8181529150602080830190848101610120808502870183018810156118b157600080fd5b60005b858110156119595781838a0312156118cb57600080fd5b6118d482612545565b833581526118e48a8686016117fa565b8582015260408401356040820152606084013560608201526080840135608082015260a084013560a082015261191d8a60c086016117fa565b60c082015261192f8a60e086016117fa565b60e08201526101006119438b8287016119ce565b90820152855293830193918101916001016118b4565b50505050505092915050565b600082601f830112611975578081fd5b81356119836118238261256c565b8181529150602080830190848101818402860182018710156119a457600080fd5b60005b848110156119c3578135845292820192908201906001016119a7565b505050505092915050565b80356108b3816125a1565b600082601f8301126119e9578081fd5b813567ffffffffffffffff8111156119ff578182fd5b611a12601f8201601f1916602001612545565b9150808252836020828501011115611a2957600080fd5b8060208401602084013760009082016020015292915050565b600060e08284031215611a53578081fd5b611a5d60e0612545565b9050813567ffffffffffffffff80821115611a7757600080fd5b611a83858386016119d9565b83526020840135915080821115611a9957600080fd5b611aa5858386016119d9565b60208401526040840135915080821115611abe57600080fd5b611aca858386016119d9565b60408401526060840135915080821115611ae357600080fd5b611aef858386016119d9565b60608401526080840135915080821115611b0857600080fd5b611b14858386016119d9565b608084015260a0840135915080821115611b2d57600080fd5b611b39858386016119d9565b60a084015260c0840135915080821115611b5257600080fd5b50611b5f84828501611b6b565b60c08301525092915050565b600060808284031215611b7c578081fd5b611b866080612545565b9050813567ffffffffffffffff80821115611ba057600080fd5b611bac8583860161186f565b83526020840135915080821115611bc257600080fd5b611bce85838601611805565b60208401526040840135915080821115611be757600080fd5b50611bf484828501611965565b6040830152506060820135606082015292915050565b600060208284031215611c1b578081fd5b81516113cc816125a1565b600060208284031215611c37578081fd5b5051919050565b60008060008060808587031215611c53578283fd5b8435611c5e8161258c565b93506020850135611c6e8161258c565b92506040850135611c7e8161258c565b91506060850135611c8e8161258c565b939692955090935050565b60008060008060808587031215611cae578182fd5b843567ffffffffffffffff80821115611cc5578384fd5b611cd188838901611a42565b955060208701359150611ce38261258c565b90935060408601359080821115611cf8578384fd5b611d04888389016119d9565b93506060870135915080821115611d19578283fd5b50611d26878288016119d9565b91505092959194509250565b60008060408385031215611d44578182fd5b823567ffffffffffffffff80821115611d5b578384fd5b611d6786838701611a42565b93506020850135915080821115611d7c578283fd5b50611d89858286016119d9565b9150509250929050565b6000815180845260208401935060208301825b82811015611dc4578151865260209586019590910190600101611da6565b5093949350505050565b15159052565b60008151808452815b81811015611df957602081850181015186830182015201611ddd565b81811115611e0a5782602083870101525b50601f01601f19169290920160200192915050565b805160808084528151908401819052600091602091839160a08701919084015b81841015611e6857611e52838251611f0a565b6001939093019261012092909201918401611e3f565b50508483015186820387850152805180835285935082850191818602840186019086015b82861015611ebc57601f19858303018452611ea8828251611dd4565b600196909601959387019391508601611e8c565b506040880151955088810360408a0152611ed68187611d93565b94505050505060608401516060860152809250505092915050565b8051825260208082015190830152604090810151910152565b80518252602081015160018060a01b03808216602085015260408301516040850152606083015160608501526080830151608085015260a083015160a08501528060c08401511660c08501528060e08401511660e085015250506101008082015161038d82850182611dce565b9889526bffffffffffffffffffffffff19606098891b811660208b015260348a0197909752605489019590955260748801939093526094870191909152841b831660b486015290921b1660c8830152151560f81b60dc82015260dd0190565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b6001600160a01b0391909116815260200190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b901515815260200190565b90815260200190565b8581526001600160a01b0385811660208301528416604082015260a081016003841061208157fe5b6060820193909352608001529392505050565b93845260ff9290921660208401526040830152606082015260800190565b6020808252601490820152734d41524b45545f4e4f545f545241444541424c4560601b604082015260600190565b602080825260139082015272544f54414c5f4245545f53495a455f5a45524f60681b604082015260600190565b60208082526019908201527f54414b45525f414d4f554e545f4e4f545f504f53495449564500000000000000604082015260600190565b6020808252601390820152721053149150511657d253925512505312569151606a1b604082015260600190565b6020808252601290820152710a6928e9c82a8aaa48abe9a92a69a82a886960731b604082015260600190565b60208082526017908201527f494e434f52524543545f41525241595f4c454e47544853000000000000000000604082015260600190565b60208082526017908201527f494e56414c49445f50455243454e544147455f4f444453000000000000000000604082015260600190565b6020808252601190820152702727aa2fa0afa9aaa822a92fa0a226a4a760791b604082015260600190565b6020808252601690820152751192531317d053149150511657d4d55093525515115160521b604082015260600190565b60208082526017908201527f53454e4445525f4d5553545f42455f4558454355544f52000000000000000000604082015260600190565b60208082526018908201527f54414b45525f5349474e41545552455f4d49534d415443480000000000000000604082015260600190565b6020808252600d908201526c13d491115497d1561412549151609a1b604082015260600190565b60208082526012908201527124a72b20a624a22fa120a9a2afaa27a5a2a760711b604082015260600190565b602080825260129082015271494e53554646494349454e545f535041434560701b604082015260600190565b602080825260169082015275494e434f4e53495354454e545f4558454355544f525360501b604082015260600190565b6020808252600f908201526e2a20a5a2a92fa727aa2fa6a0a5a2a960891b604082015260600190565b6020808252601b908201527f4558454355544f525f5349474e41545552455f4d49534d415443480000000000604082015260600190565b6020808252601c908201527f43414e4e4f545f5452414e534645525f54414b45525f455343524f5700000000604082015260600190565b600060208252825160e06020840152612437610100840182611dd4565b60208501519150601f19808583030160408601526124558284611dd4565b60408701519350818682030160608701526124708185611dd4565b925050606086015192508085830301608086015261248e8284611dd4565b60808701519350818682030160a08701526124a98185611dd4565b92505060a08601519250808583030160c08601526124c78284611dd4565b60c08701519350818682030160e08701526124e28185611e1f565b979650505050505050565b61014081016124fc8285611f0a565b826101208301529392505050565b85815260208101859052604081018490526101e0810161252d6060830185611f0a565b61253b610180830184611ef1565b9695505050505050565b60405181810167ffffffffffffffff8111828210171561256457600080fd5b604052919050565b600067ffffffffffffffff821115612582578081fd5b5060209081020190565b6001600160a01b03811681146114b757600080fd5b80151581146114b757600080fdfea365627a7a72315820af59bc471fef2ae8427d4dcfc1cce3d5f11d7b83e8d4a51016d4186688de536f6c6578706572696d656e74616cf564736f6c6343000510004000000000000000000000000087d712688a706d4343704eeb382cb72abe76452e00000000000000000000000090c997f83885b4bd16d3ef8add73b9d901d49095

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061004c5760003560e01c8063158ef93e14610051578063220bfc541461006f5780639a89f58914610084578063f8c8765e14610097575b600080fd5b6100596100aa565b6040516100669190612045565b60405180910390f35b61008261007d366004611d32565b6100b3565b005b610082610092366004611c99565b610393565b6100826100a5366004611c3e565b6106d2565b60005460ff1681565b60008260c00151600001516000815181106100ca57fe5b602002602001015160e00151905060008360c0015160400151518460c001516000015151148015610106575060c0840151602081015151905151145b61012b5760405162461bcd60e51b81526004016101229061219d565b60405180910390fd5b6001600160a01b0382161561036f576005546040516334640aad60e21b81526001600160a01b039091169063d1902ab49061016a90879060040161241a565b60206040518083038186803b15801561018257600080fd5b505afa158015610196573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506101ba9190810190611c26565b600154604051631a5ab2cb60e31b81529192506001600160a01b03169063d2d59658906101eb908490600401612050565b60206040518083038186803b15801561020357600080fd5b505afa158015610217573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061023b9190810190611c0a565b156102585760405162461bcd60e51b815260040161012290612236565b816001600160a01b031661026c82856107f8565b6001600160a01b0316146102925760405162461bcd60e51b8152600401610122906123ac565b60c084015151516001101561030c5760015b60c0850151515181101561030a57826001600160a01b03168560c001516000015182815181106102d057fe5b602002602001015160e001516001600160a01b0316146103025760405162461bcd60e51b815260040161012290612353565b6001016102a4565b505b6001546040516339d63abd60e21b81526001600160a01b039091169063e758eaf49061033c908490600401612050565b600060405180830381600087803b15801561035657600080fd5b505af115801561036a573d6000803e3d6000fd5b505050505b60c08401518051604082015160209092015161038d929033856108b9565b50505050565b6005546040516334640aad60e21b81526000916001600160a01b03169063d1902ab4906103c490889060040161241a565b60206040518083038186803b1580156103dc57600080fd5b505afa1580156103f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104149190810190611c26565b9050836001600160a01b031661042a82856107f8565b6001600160a01b0316146104505760405162461bcd60e51b81526004016101229061229d565b600154604051631a5ab2cb60e31b81526001600160a01b039091169063d2d5965890610480908490600401612050565b60206040518083038186803b15801561049857600080fd5b505afa1580156104ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104d09190810190611c0a565b156104ed5760405162461bcd60e51b815260040161012290612236565b60008560c001516000015160008151811061050457fe5b602002602001015160e00151905060006001600160a01b0316816001600160a01b03161461058e57336001600160a01b038216146105545760405162461bcd60e51b815260040161012290612266565b806001600160a01b031661056883856107f8565b6001600160a01b03161461058e5760405162461bcd60e51b8152600401610122906123ac565b60c08601516040810151519051511480156105b4575060c0860151602081015151905151145b6105d05760405162461bcd60e51b81526004016101229061219d565b60c086015151516001101561064a5760015b60c0870151515181101561064857816001600160a01b03168760c0015160000151828151811061060e57fe5b602002602001015160e001516001600160a01b0316146106405760405162461bcd60e51b815260040161012290612353565b6001016105e2565b505b60c086015180516040820151602090920151610668929088866108b9565b6001546040516339d63abd60e21b81526001600160a01b039091169063e758eaf490610698908590600401612050565b600060405180830381600087803b1580156106b257600080fd5b505af11580156106c6573d6000803e3d6000fd5b50505050505050505050565b60005460ff16156106f55760405162461bcd60e51b815260040161012290612144565b60035460405163df7f453b60e01b815233916001600160a01b03169063df7f453b90610725908490600401612007565b60206040518083038186803b15801561073d57600080fd5b505afa158015610751573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107759190810190611c0a565b6107915760405162461bcd60e51b81526004016101229061220b565b50600180546001600160a01b039586166001600160a01b031991821617825560028054958716958216959095179094556000805460048054948816949096169390931790945560ff199290941661010002610100600160a81b031990911617169091179055565b600080600080845160411461081357600093505050506108b3565b50505060208201516040830151606084015160001a601b81101561083557601b015b8060ff16601b1415801561084d57508060ff16601c14155b1561085e57600093505050506108b3565b600186828585604051600081526020016040526040516108819493929190612094565b6020604051602081039080840390855afa1580156108a3573d6000803e3d6000fd5b5050506020604051035193505050505b92915050565b60006108c786868686610930565b905080156108e0576108db86868585610a9e565b610928565b60005b86518110156109265761091e8782815181106108fb57fe5b602002602001015187838151811061090f57fe5b60200260200101518686610ae4565b6001016108e3565b505b505050505050565b6000808560008151811061094057fe5b60200260200101516101000151905060008660008151811061095e57fe5b602002602001015160000151905060008760008151811061097b57fe5b602002602001015160200151905060008090505b88518110156109e5576109dd8982815181106109a757fe5b60200260200101518983815181106109bb57fe5b6020026020010151888a85815181106109d057fe5b6020026020010151610b04565b60010161098f565b50600188511115610a8e5760015b8851811015610a8c57831515898281518110610a0b57fe5b602002602001015161010001511515141580610a3e575082898281518110610a2f57fe5b60200260200101516000015114155b80610a725750816001600160a01b0316898281518110610a5a57fe5b6020026020010151602001516001600160a01b031614155b15610a84576000945050505050610a96565b6001016109f3565b505b600193505050505b949350505050565b610aa66117d9565b610ab08585610c70565b9050610ad185600081518110610ac257fe5b60200260200101518285610ce6565b610add85858585610d01565b5050505050565b610aec6117d9565b610af68585610eb6565b9050610add85828585610f2b565b60008311610b245760405162461bcd60e51b81526004016101229061210d565b610b3584838363ffffffff61103216565b600480548551604051637d4b2a1960e01b81526001600160a01b0390921692637d4b2a1992610b65929101612050565b60206040518083038186803b158015610b7d57600080fd5b505afa158015610b91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610bb59190810190611c26565b15610bd25760405162461bcd60e51b8152600401610122906120b2565b60015460405163a5f650d760e01b81526001600160a01b039091169063a5f650d790610c0490879087906004016124ed565b60206040518083038186803b158015610c1c57600080fd5b505afa158015610c30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610c549190810190611c0a565b61038d5760405162461bcd60e51b815260040161012290612327565b610c786117d9565b610c806117d9565b835160005b81811015610cdc57610c956117d9565b610cc5878381518110610ca457fe5b6020026020010151878481518110610cb857fe5b6020026020010151610eb6565b9050610cd18482611097565b935050600101610c85565b5090949350505050565b610cf1838383611109565b610cfc8383836112e3565b505050565b60005b8451811015610add57610d156117d9565b610d38868381518110610d2457fe5b6020026020010151868481518110610cb857fe5b60015487519192506000916001600160a01b039091169063c9f67f9c90899086908110610d6157fe5b602002602001015184600001516040518363ffffffff1660e01b8152600401610d8b9291906124ed565b602060405180830381600087803b158015610da557600080fd5b505af1158015610db9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ddd9190810190611c26565b9050610dfc878481518110610dee57fe5b602002602001015183611323565b846001600160a01b0316878481518110610e1257fe5b602002602001015160000151888581518110610e2a57fe5b602002602001015160c001516001600160a01b03167f7fce7b83d2014c90bf64f0281296c1ecf7429a9473167b683f3f14c55bfe9e1f84610e7d8c8981518110610e7057fe5b602002602001015161133b565b898d8a81518110610e8a57fe5b602002602001015189604051610ea495949392919061250a565b60405180910390a45050600101610d04565b610ebe6117d9565b6000610ec8611398565b90506000610ef38560600151610ee784876113a590919063ffffffff16565b9063ffffffff6113d316565b90506000610f07828663ffffffff6113f516565b60408051606081018252968752602087019190915285019190915250919392505050565b600154835160405163327d9fe760e21b81526000926001600160a01b03169163c9f67f9c91610f5e9189916004016124ed565b602060405180830381600087803b158015610f7857600080fd5b505af1158015610f8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610fb09190810190611c26565b9050610fbc8585611323565b610fc7858585610ce6565b826001600160a01b031685600001518660c001516001600160a01b03167f7fce7b83d2014c90bf64f0281296c1ecf7429a9473167b683f3f14c55bfe9e1f8461100f8a61133b565b878b8b60405161102395949392919061250a565b60405180910390a45050505050565b61103b8361140a565b61104583826114ba565b6110615760405162461bcd60e51b815260040161012290612171565b816001600160a01b03168360c001516001600160a01b03161415610cfc5760405162461bcd60e51b815260040161012290612383565b61109f6117d9565b60408051606081019091528251845182916110c0919063ffffffff6114fa16565b81526020016110e0846020015186602001516114fa90919063ffffffff16565b8152602001611100846040015186604001516114fa90919063ffffffff16565b90529392505050565b82610100015115611201576002805484516020860151604080870151905163c6b4931560e01b81526001600160a01b039094169463c6b4931594611154949392889291600401612059565b600060405180830381600087803b15801561116e57600080fd5b505af1158015611182573d6000803e3d6000fd5b50506002805486516020808901519088015160405163904e531b60e01b81526001600160a01b03909416965063904e531b95506111ca94929391928892909190600401612059565b600060405180830381600087803b1580156111e457600080fd5b505af11580156111f8573d6000803e3d6000fd5b50505050610cfc565b60025483516020850151604080860151905163c6b4931560e01b81526001600160a01b039094169363c6b493159361124493909290918791600191600401612059565b600060405180830381600087803b15801561125e57600080fd5b505af1158015611272573d6000803e3d6000fd5b505060025485516020808801519087015160405163904e531b60e01b81526001600160a01b03909416955063904e531b94506112b5938791600191600401612059565b600060405180830381600087803b1580156112cf57600080fd5b505af1158015610926573d6000803e3d6000fd5b602080840151600254918401516113079284916001600160a01b039091169061150c565b610cfc5760405162461bcd60e51b8152600401610122906123e3565b61132d82826115a2565b6113378282611786565b5050565b80516020808301516040808501516060860151608087015160a088015160c089015160e08a01516101008b0151965160009a61137b9a9099989101611f77565b604051602081830303815290604052805190602001209050919050565b68056bc75e2d6310000090565b6000826113b4575060006108b3565b828202828482816113c157fe5b04146113cc57600080fd5b9392505050565b60008082116113e157600080fd5b60008284816113ec57fe5b04949350505050565b60008282111561140457600080fd5b50900390565b600081604001511161142e5760405162461bcd60e51b8152600401610122906120e0565b6000816060015111801561144e575068056bc75e2d631000008160600151105b61146a5760405162461bcd60e51b8152600401610122906121d4565b60208101516001600160a01b03166114945760405162461bcd60e51b8152600401610122906122fb565b428160800151116114b75760405162461bcd60e51b8152600401610122906122d4565b50565b6000806114c68461133b565b90508360c001516001600160a01b03166114e86114e2836117c6565b856107f8565b6001600160a01b031614949350505050565b6000828201838110156113cc57600080fd5b60008054604051630aed65f560e11b81526101009091046001600160a01b0316906315dacbea9061154790889088908890889060040161201b565b602060405180830381600087803b15801561156157600080fd5b505af1158015611575573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115999190810190611c0a565b95945050505050565b8161010001511561169f576002548251602084015160c0850151604080860151905163c6b4931560e01b81526001600160a01b039095169463c6b49315946115f69490939092909160019190600401612059565b600060405180830381600087803b15801561161057600080fd5b505af1158015611624573d6000803e3d6000fd5b50506002548451602086015160c0870151865160405163904e531b60e01b81526001600160a01b03909516965063904e531b95506116689460019190600401612059565b600060405180830381600087803b15801561168257600080fd5b505af1158015611696573d6000803e3d6000fd5b50505050611337565b600280548351602085015160c0860151604080870151905163c6b4931560e01b81526001600160a01b039095169563c6b49315956116e39594939290600401612059565b600060405180830381600087803b1580156116fd57600080fd5b505af1158015611711573d6000803e3d6000fd5b5050600280548551602087015160c0880151875160405163904e531b60e01b81526001600160a01b03909516975063904e531b965061175895939492939192600401612059565b600060405180830381600087803b15801561177257600080fd5b505af1158015610928573d6000803e3d6000fd5b602082015160c083015160025483516117aa9392916001600160a01b03169061150c565b6113375760405162461bcd60e51b8152600401610122906123e3565b60008160405160200161137b9190611fd6565b60405180606001604052806000815260200160008152602001600081525090565b80356108b38161258c565b600082601f830112611815578081fd5b81356118286118238261256c565b612545565b8181529150602080830190840160005b838110156118655761185087602084358901016119d9565b83526020928301929190910190600101611838565b5050505092915050565b600082601f83011261187f578081fd5b813561188d6118238261256c565b8181529150602080830190848101610120808502870183018810156118b157600080fd5b60005b858110156119595781838a0312156118cb57600080fd5b6118d482612545565b833581526118e48a8686016117fa565b8582015260408401356040820152606084013560608201526080840135608082015260a084013560a082015261191d8a60c086016117fa565b60c082015261192f8a60e086016117fa565b60e08201526101006119438b8287016119ce565b90820152855293830193918101916001016118b4565b50505050505092915050565b600082601f830112611975578081fd5b81356119836118238261256c565b8181529150602080830190848101818402860182018710156119a457600080fd5b60005b848110156119c3578135845292820192908201906001016119a7565b505050505092915050565b80356108b3816125a1565b600082601f8301126119e9578081fd5b813567ffffffffffffffff8111156119ff578182fd5b611a12601f8201601f1916602001612545565b9150808252836020828501011115611a2957600080fd5b8060208401602084013760009082016020015292915050565b600060e08284031215611a53578081fd5b611a5d60e0612545565b9050813567ffffffffffffffff80821115611a7757600080fd5b611a83858386016119d9565b83526020840135915080821115611a9957600080fd5b611aa5858386016119d9565b60208401526040840135915080821115611abe57600080fd5b611aca858386016119d9565b60408401526060840135915080821115611ae357600080fd5b611aef858386016119d9565b60608401526080840135915080821115611b0857600080fd5b611b14858386016119d9565b608084015260a0840135915080821115611b2d57600080fd5b611b39858386016119d9565b60a084015260c0840135915080821115611b5257600080fd5b50611b5f84828501611b6b565b60c08301525092915050565b600060808284031215611b7c578081fd5b611b866080612545565b9050813567ffffffffffffffff80821115611ba057600080fd5b611bac8583860161186f565b83526020840135915080821115611bc257600080fd5b611bce85838601611805565b60208401526040840135915080821115611be757600080fd5b50611bf484828501611965565b6040830152506060820135606082015292915050565b600060208284031215611c1b578081fd5b81516113cc816125a1565b600060208284031215611c37578081fd5b5051919050565b60008060008060808587031215611c53578283fd5b8435611c5e8161258c565b93506020850135611c6e8161258c565b92506040850135611c7e8161258c565b91506060850135611c8e8161258c565b939692955090935050565b60008060008060808587031215611cae578182fd5b843567ffffffffffffffff80821115611cc5578384fd5b611cd188838901611a42565b955060208701359150611ce38261258c565b90935060408601359080821115611cf8578384fd5b611d04888389016119d9565b93506060870135915080821115611d19578283fd5b50611d26878288016119d9565b91505092959194509250565b60008060408385031215611d44578182fd5b823567ffffffffffffffff80821115611d5b578384fd5b611d6786838701611a42565b93506020850135915080821115611d7c578283fd5b50611d89858286016119d9565b9150509250929050565b6000815180845260208401935060208301825b82811015611dc4578151865260209586019590910190600101611da6565b5093949350505050565b15159052565b60008151808452815b81811015611df957602081850181015186830182015201611ddd565b81811115611e0a5782602083870101525b50601f01601f19169290920160200192915050565b805160808084528151908401819052600091602091839160a08701919084015b81841015611e6857611e52838251611f0a565b6001939093019261012092909201918401611e3f565b50508483015186820387850152805180835285935082850191818602840186019086015b82861015611ebc57601f19858303018452611ea8828251611dd4565b600196909601959387019391508601611e8c565b506040880151955088810360408a0152611ed68187611d93565b94505050505060608401516060860152809250505092915050565b8051825260208082015190830152604090810151910152565b80518252602081015160018060a01b03808216602085015260408301516040850152606083015160608501526080830151608085015260a083015160a08501528060c08401511660c08501528060e08401511660e085015250506101008082015161038d82850182611dce565b9889526bffffffffffffffffffffffff19606098891b811660208b015260348a0197909752605489019590955260748801939093526094870191909152841b831660b486015290921b1660c8830152151560f81b60dc82015260dd0190565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b6001600160a01b0391909116815260200190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b901515815260200190565b90815260200190565b8581526001600160a01b0385811660208301528416604082015260a081016003841061208157fe5b6060820193909352608001529392505050565b93845260ff9290921660208401526040830152606082015260800190565b6020808252601490820152734d41524b45545f4e4f545f545241444541424c4560601b604082015260600190565b602080825260139082015272544f54414c5f4245545f53495a455f5a45524f60681b604082015260600190565b60208082526019908201527f54414b45525f414d4f554e545f4e4f545f504f53495449564500000000000000604082015260600190565b6020808252601390820152721053149150511657d253925512505312569151606a1b604082015260600190565b6020808252601290820152710a6928e9c82a8aaa48abe9a92a69a82a886960731b604082015260600190565b60208082526017908201527f494e434f52524543545f41525241595f4c454e47544853000000000000000000604082015260600190565b60208082526017908201527f494e56414c49445f50455243454e544147455f4f444453000000000000000000604082015260600190565b6020808252601190820152702727aa2fa0afa9aaa822a92fa0a226a4a760791b604082015260600190565b6020808252601690820152751192531317d053149150511657d4d55093525515115160521b604082015260600190565b60208082526017908201527f53454e4445525f4d5553545f42455f4558454355544f52000000000000000000604082015260600190565b60208082526018908201527f54414b45525f5349474e41545552455f4d49534d415443480000000000000000604082015260600190565b6020808252600d908201526c13d491115497d1561412549151609a1b604082015260600190565b60208082526012908201527124a72b20a624a22fa120a9a2afaa27a5a2a760711b604082015260600190565b602080825260129082015271494e53554646494349454e545f535041434560701b604082015260600190565b602080825260169082015275494e434f4e53495354454e545f4558454355544f525360501b604082015260600190565b6020808252600f908201526e2a20a5a2a92fa727aa2fa6a0a5a2a960891b604082015260600190565b6020808252601b908201527f4558454355544f525f5349474e41545552455f4d49534d415443480000000000604082015260600190565b6020808252601c908201527f43414e4e4f545f5452414e534645525f54414b45525f455343524f5700000000604082015260600190565b600060208252825160e06020840152612437610100840182611dd4565b60208501519150601f19808583030160408601526124558284611dd4565b60408701519350818682030160608701526124708185611dd4565b925050606086015192508085830301608086015261248e8284611dd4565b60808701519350818682030160a08701526124a98185611dd4565b92505060a08601519250808583030160c08601526124c78284611dd4565b60c08701519350818682030160e08701526124e28185611e1f565b979650505050505050565b61014081016124fc8285611f0a565b826101208301529392505050565b85815260208101859052604081018490526101e0810161252d6060830185611f0a565b61253b610180830184611ef1565b9695505050505050565b60405181810167ffffffffffffffff8111828210171561256457600080fd5b604052919050565b600067ffffffffffffffff821115612582578081fd5b5060209081020190565b6001600160a01b03811681146114b757600080fd5b80151581146114b757600080fdfea365627a7a72315820af59bc471fef2ae8427d4dcfc1cce3d5f11d7b83e8d4a51016d4186688de536f6c6578706572696d656e74616cf564736f6c63430005100040

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000087d712688a706d4343704eeb382cb72abe76452e00000000000000000000000090c997f83885b4bd16d3ef8add73b9d901d49095

-----Decoded View---------------
Arg [0] : _superAdminRole (address): 0x87d712688a706d4343704eEB382CB72aBE76452e
Arg [1] : _eip712FillHasher (address): 0x90C997f83885B4Bd16D3ef8ADD73B9d901d49095

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000087d712688a706d4343704eeb382cb72abe76452e
Arg [1] : 00000000000000000000000090c997f83885b4bd16d3ef8add73b9d901d49095


Deployed Bytecode Sourcemap

350:9218:18:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;350:9218:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55:23:2;;;:::i;:::-;;;;;;;;;;;;;;;;833:1526:18;;;;;;;;;:::i;:::-;;2694:1792;;;;;;;;;:::i;1651:411:14:-;;;;;;;;;:::i;55:23:2:-;;;;;;:::o;833:1526:18:-;971:16;990:11;:17;;;:24;;;1015:1;990:27;;;;;;;;;;;;;;:36;;;971:55;;1036:16;1119:11;:17;;;:30;;;:37;1084:11;:17;;;:24;;;:31;:72;:157;;;;-1:-1:-1;1207:17:18;;;;:27;;;;:34;1172:24;;:31;:69;1084:157;1063:227;;;;-1:-1:-1;;;1063:227:18;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1305:22:18;;;1301:850;;1354:16;;:44;;-1:-1:-1;;;1354:44:18;;-1:-1:-1;;;;;1354:16:18;;;;:31;;:44;;1386:11;;1354:44;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1354:44:18;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1354:44:18;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1354:44:18;;;;;;;;;1438:5;;:36;;-1:-1:-1;;;1438:36:18;;1343:55;;-1:-1:-1;;;;;;1438:5:18;;:26;;:36;;1343:55;;1438:36;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1438:36:18;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1438:36:18;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1438:36:18;;;;;;;;;:45;1413:126;;;;-1:-1:-1;;;1413:126:18;;;;;;;;;1677:8;-1:-1:-1;;;;;1579:106:18;:94;1614:8;1644:11;1579:13;:94::i;:::-;-1:-1:-1;;;;;1579:106:18;;1554:192;;;;-1:-1:-1;;;1554:192:18;;;;;;;;;1765:17;;;;:24;:31;1799:1;-1:-1:-1;1761:329:18;;;1837:1;1820:256;1844:17;;;;:24;:31;1840:35;;1820:256;;;1977:8;-1:-1:-1;;;;;1937:48:18;:11;:17;;;:24;;;1962:1;1937:27;;;;;;;;;;;;;;:36;;;-1:-1:-1;;;;;1937:48:18;;1904:153;;;;-1:-1:-1;;;1904:153:18;;;;;;;;;1877:3;;1820:256;;;;1761:329;2104:5;;:36;;-1:-1:-1;;;2104:36:18;;-1:-1:-1;;;;;2104:5:18;;;;:26;;:36;;2131:8;;2104:36;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2104:36:18;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2104:36:18;;;;1301:850;2186:17;;;;:24;;2224:30;;;;2268:27;;;;;2161:190;;2224:30;2309:10;2333:8;2161:11;:190::i;:::-;833:1526;;;;:::o;2694:1792::-;2909:16;;:44;;-1:-1:-1;;;2909:44:18;;2890:16;;-1:-1:-1;;;;;2909:16:18;;:31;;:44;;2941:11;;2909:44;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2909:44:18;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2909:44:18;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;2909:44:18;;;;;;;;;2890:63;;3068:5;-1:-1:-1;;;;;2985:88:18;:79;3016:8;3042;2985:13;:79::i;:::-;-1:-1:-1;;;;;2985:88:18;;2964:159;;;;-1:-1:-1;;;2964:159:18;;;;;;;;;3155:5;;:36;;-1:-1:-1;;;3155:36:18;;-1:-1:-1;;;;;3155:5:18;;;;:26;;:36;;3182:8;;3155:36;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3155:36:18;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3155:36:18;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;3155:36:18;;;;;;;;;:45;3134:114;;;;-1:-1:-1;;;3134:114:18;;;;;;;;;3259:16;3278:11;:17;;;:24;;;3303:1;3278:27;;;;;;;;;;;;;;:36;;;3259:55;;3349:1;-1:-1:-1;;;;;3329:22:18;:8;-1:-1:-1;;;;;3329:22:18;;3325:363;;3392:10;-1:-1:-1;;;;;3392:22:18;;;3367:104;;;;-1:-1:-1;;;3367:104:18;;;;;;;;;3608:8;-1:-1:-1;;;;;3510:106:18;:94;3545:8;3575:11;3510:13;:94::i;:::-;-1:-1:-1;;;;;3510:106:18;;3485:192;;;;-1:-1:-1;;;3485:192:18;;;;;;;;;3754:17;;;;:30;;;;:37;3719:24;;:31;:72;:157;;;;-1:-1:-1;3842:17:18;;;;:27;;;;:34;3807:24;;:31;:69;3719:157;3698:227;;;;-1:-1:-1;;;3698:227:18;;;;;;;;;3940:17;;;;:24;:31;3974:1;-1:-1:-1;3936:301:18;;;4008:1;3991:236;4015:17;;;;:24;:31;4011:35;;3991:236;;;4140:8;-1:-1:-1;;;;;4100:48:18;:11;:17;;;:24;;;4125:1;4100:27;;;;;;;;;;;;;;:36;;;-1:-1:-1;;;;;4100:48:18;;4071:141;;;;-1:-1:-1;;;4071:141:18;;;;;;;;;4048:3;;3991:236;;;;3936:301;4272:17;;;;:24;;4310:30;;;;4354:27;;;;;4247:185;;4310:30;4395:5;4414:8;4247:11;:185::i;:::-;4443:5;;:36;;-1:-1:-1;;;4443:36:18;;-1:-1:-1;;;;;4443:5:18;;;;:26;;:36;;4470:8;;4443:36;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4443:36:18;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;4443:36:18;;;;2694:1792;;;;;;:::o;1651:411:14:-;200:11:2;;;;199:12;191:44;;;;-1:-1:-1;;;191:44:2;;;;;;;;;2250:14:14;;:37;;-1:-1:-1;;;2250:37:14;;1880:10;;-1:-1:-1;;;;;2250:14:14;;:27;;:37;;1880:10;;2250:37;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2250:37:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2250:37:14;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;2250:37:14;;;;;;;;;2229:101;;;;-1:-1:-1;;;2229:101:14;;;;;;;;;-1:-1:-1;1906:5:14;:14;;-1:-1:-1;;;;;1906:14:14;;;-1:-1:-1;;;;;;1906:14:14;;;;;;1930:6;:16;;;;;;;;;;;;;;;1906:5;1956:27;;1993:15;:34;;;;;;;;;;;;;;;;-1:-1:-1;;1956:27:14;;;;1906:14;1956:27;-1:-1:-1;;;;;;1956:27:14;;;;2037:18;;;;;;1651:411::o;609:1026:41:-;687:7;706:9;725;744:7;804:9;:16;824:2;804:22;800:72;;858:1;842:19;;;;;;;800:72;-1:-1:-1;;;1166:4:41;1151:20;;1145:27;1211:4;1196:20;;1190:27;1264:4;1249:20;;1243:27;1240:1;1235:36;1390:2;1386:6;;1382:44;;;1413:2;1408:7;1382:44;1503:1;:7;;1508:2;1503:7;;:18;;;;;1514:1;:7;;1519:2;1514:7;;1503:18;1499:130;;;1553:1;1537:19;;;;;;;1499:130;1594:24;1604:4;1610:1;1613;1616;1594:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1594:24:41;;;;;;;;1587:31;;;;;609:1026;;;;;:::o;4951:922:18:-;5175:21;5199:127;5237:11;5262:12;5288:9;5311:5;5199:24;:127::i;:::-;5175:151;;5408:16;5404:463;;;5440:140;5476:11;5505:12;5535:5;5558:8;5440:18;:140::i;:::-;5404:463;;;5616:9;5611:246;5635:11;:18;5631:1;:22;5611:246;;;5678:164;5716:11;5728:1;5716:14;;;;;;;;;;;;;;5752:12;5765:1;5752:15;;;;;;;;;;;;;;5789:5;5816:8;5678:16;:164::i;:::-;5655:3;;5611:246;;;;5404:463;4951:922;;;;;;:::o;7202:1098::-;7429:4;7449:29;7481:11;7493:1;7481:14;;;;;;;;;;;;;;:39;;;7449:71;;7530:18;7551:11;7563:1;7551:14;;;;;;;;;;;;;;:25;;;7530:46;;7586:17;7606:11;7618:1;7606:14;;;;;;;;;;;;;;:24;;;7586:44;;7646:9;7658:1;7646:13;;7641:222;7665:11;:18;7661:1;:22;7641:222;;;7704:148;7738:11;7750:1;7738:14;;;;;;;;;;;;;;7770:12;7783:1;7770:15;;;;;;;;;;;;;;7803:5;7826:9;7836:1;7826:12;;;;;;;;;;;;;;7704:16;:148::i;:::-;7685:3;;7641:222;;;;7898:1;7877:11;:18;:22;7873:400;;;7932:1;7915:348;7939:11;:18;7935:1;:22;7915:348;;;8029:24;7986:67;;:11;7998:1;7986:14;;;;;;;;;;;;;;:39;;;:67;;;;:130;;;;8106:10;8077:11;8089:1;8077:14;;;;;;;;;;;;;;:25;;;:39;;7986:130;:191;;;;8168:9;-1:-1:-1;;;;;8140:37:18;:11;8152:1;8140:14;;;;;;;;;;;;;;:24;;;-1:-1:-1;;;;;8140:37:18;;;7986:191;7982:267;;;8225:5;8218:12;;;;;;;;7982:267;7959:3;;7915:348;;;;7873:400;8289:4;8282:11;;;;;7202:1098;;;;;;;:::o;6249:612::-;6446:53;;:::i;:::-;6502:101;6556:11;6581:12;6502:40;:101::i;:::-;6446:157;;6614:107;6647:11;6659:1;6647:14;;;;;;;;;;;;;;6675:17;6706:5;6614:19;:107::i;:::-;6732:122;6766:11;6791:12;6817:5;6836:8;6732:20;:122::i;:::-;6249:612;;;;;:::o;2620:448:14:-;2798:48;;:::i;:::-;2849:89;2898:5;2917:11;2849:35;:89::i;:::-;2798:140;;2949:112;2979:5;2998:12;3024:5;3043:8;2949:16;:112::i;5647:584::-;5878:1;5864:11;:15;5843:87;;;;-1:-1:-1;;;5843:87:14;;;;;;;;;5940:41;:5;5965;5972:8;5940:41;:24;:41;:::i;:::-;6012:15;;;6042:16;;6012:47;;-1:-1:-1;;;6012:47:14;;-1:-1:-1;;;;;6012:15:14;;;;:29;;:47;;6042:16;6012:47;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;6012:47:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6012:47:14;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;6012:47:14;;;;;;;;;:52;5991:119;;;;-1:-1:-1;;;5991:119:14;;;;;;;;;6141:5;;:39;;-1:-1:-1;;;6141:39:14;;-1:-1:-1;;;;;6141:5:14;;;;:19;;:39;;6161:5;;6168:11;;6141:39;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;6141:39:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6141:39:14;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;6141:39:14;;;;;;;;;6120:104;;;;-1:-1:-1;;;6120:104:14;;;;;;;;2429:700:37;2600:35;;:::i;:::-;2651:56;;:::i;:::-;2745:18;;2717:25;2773:313;2797:17;2793:1;:21;2773:313;;;2835:48;;:::i;:::-;2886:98;2923:11;2935:1;2923:14;;;;;;;;;;;;;;2955:12;2968:1;2955:15;;;;;;;;;;;;;;2886:19;:98::i;:::-;2835:149;;3021:54;3040:20;3062:12;3021:18;:54::i;:::-;2998:77;-1:-1:-1;;2816:3:37;;2773:313;;;-1:-1:-1;3102:20:37;;2429:700;-1:-1:-1;;;;2429:700:37:o;4939:395:14:-;5123:96;5159:5;5178:12;5204:5;5123:22;:96::i;:::-;5230:97;5267:5;5286:12;5312:5;5230:23;:97::i;:::-;4939:395;;;:::o;8608:958:18:-;8812:9;8807:753;8831:11;:18;8827:1;:22;8807:753;;;8870:48;;:::i;:::-;8921:114;8974:11;8986:1;8974:14;;;;;;;;;;;;;;9006:12;9019:1;9006:15;;;;;;;8921:114;9074:5;;9085:14;;8870:165;;-1:-1:-1;9050:21:18;;-1:-1:-1;;;;;9074:5:18;;;;:10;;9085:11;;9097:1;;9085:14;;;;;;;;;;;;9101:12;:24;;;9074:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9074:52:18;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;9074:52:18;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;9074:52:18;;;;;;;;;9050:76;;9141:95;9178:11;9190:1;9178:14;;;;;;;;;;;;;;9210:12;9141:19;:95::i;:::-;9364:5;-1:-1:-1;;;;;9256:293:18;9321:11;9333:1;9321:14;;;;;;;;;;;;;;:25;;;9283:11;9295:1;9283:14;;;;;;;;;;;;;;:20;;;-1:-1:-1;;;;;9256:293:18;;9387:13;9418:29;:11;9430:1;9418:14;;;;;;;;;;;;;;:27;:29::i;:::-;9465:8;9491:11;9503:1;9491:14;;;;;;;;;;;;;;9523:12;9256:293;;;;;;;;;;;;;;;;;;;-1:-1:-1;;8851:3:18;;8807:753;;795:561:37;943:35;;:::i;:::-;994:21;1018:27;:25;:27::i;:::-;994:51;;1055:15;1073:56;1108:5;:20;;;1073:30;1089:13;1073:11;:15;;:30;;;;:::i;:::-;:34;:56;:34;:56;:::i;:::-;1055:74;-1:-1:-1;1139:19:37;1161:24;1055:74;1173:11;1161:24;:11;:24;:::i;:::-;1203:146;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1203:146:37;;795:561;-1:-1:-1;;;795:561:37:o;3421:707:14:-;3652:5;;3670:24;;3652:43;;-1:-1:-1;;;3652:43:14;;3628:21;;-1:-1:-1;;;;;3652:5:14;;:10;;:43;;3663:5;;3652:43;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3652:43:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3652:43:14;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;3652:43:14;;;;;;;;;3628:67;;3706:74;3739:5;3758:12;3706:19;:74::i;:::-;3791:93;3824:5;3843:12;3869:5;3791:19;:93::i;:::-;3978:5;-1:-1:-1;;;;;3900:221:14;3948:5;:16;;;3923:5;:11;;;-1:-1:-1;;;;;3900:221:14;;3997:13;4024:20;:5;:18;:20::i;:::-;4058:8;4080:5;4099:12;3900:221;;;;;;;;;;;;;;;;;;;3421:707;;;;;:::o;3231:305:36:-;3341:24;3359:5;3341:17;:24::i;:::-;3396:31;3411:5;3418:8;3396:14;:31::i;:::-;3375:96;;;;-1:-1:-1;;;3375:96:36;;;;;;;;;3504:5;-1:-1:-1;;;;;3489:20:36;:5;:11;;;-1:-1:-1;;;;;3489:20:36;;;3481:48;;;;-1:-1:-1;;;3481:48:36;;;;;;;;1604:533:37;1801:35;;:::i;:::-;1859:271;;;;;;;;;1944:24;;1915;;1859:271;;1915:54;;:24;:54;:28;:54;:::i;:::-;1859:271;;;;1996:54;2025:12;:24;;;1996:12;:24;;;:28;;:54;;;;:::i;:::-;1859:271;;;;2073:46;2098:12;:20;;;2073:12;:20;;;:24;;:46;;;;:::i;:::-;1859:271;;1852:278;1604:533;-1:-1:-1;;;1604:533:37:o;7034:1184:14:-;7224:5;:30;;;7220:992;;;7270:6;;;7315:16;;7349:15;;;;7453:20;;;;;7270:217;;-1:-1:-1;;;7270:217:14;;-1:-1:-1;;;;;7270:6:14;;;;:27;;:217;;7315:16;7349:15;7382:5;;7270:6;:217;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;7270:217:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;7501:6:14;;;7544:16;;7578:15;;;;;7682:24;;;;7501:219;;-1:-1:-1;;;7501:219:14;;-1:-1:-1;;;;;7501:6:14;;;;-1:-1:-1;7501:25:14;;-1:-1:-1;7501:219:14;;7544:16;;7578:15;;7611:5;;7501:6;;7682:24;7501:219;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;7501:219:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7501:219:14;;;;7220:992;;;7751:6;;7796:16;;7830:15;;;;7934:20;;;;;7751:217;;-1:-1:-1;;;7751:217:14;;-1:-1:-1;;;;;7751:6:14;;;;:27;;:217;;7796:16;;7830:15;;7863:5;;7751:6;;:217;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;7751:217:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;7982:6:14;;8025:16;;8059:15;;;;;8163:24;;;;7982:219;;-1:-1:-1;;;7982:219:14;;-1:-1:-1;;;;;7982:6:14;;;;-1:-1:-1;7982:25:14;;-1:-1:-1;7982:219:14;;8092:5;;7982:6;;:219;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;7982:219:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;10511:430:14;10753:15;;;;;10817:6;;10842:24;;;;10719:161;;10786:5;;-1:-1:-1;;;;;10817:6:14;;;;10719:16;:161::i;:::-;10698:236;;;;-1:-1:-1;;;10698:236:14;;;;;;;;4343:334;4504:77;4540:5;4559:12;4504:22;:77::i;:::-;4592:78;4629:5;4648:12;4592:23;:78::i;:::-;4343:334;;:::o;4107:469:36:-;4255:16;;4289:15;;;;;4322:18;;;;;4358:20;;;;4396:12;;;;4426:10;;;;4454:11;;;;4483:14;;;;4515:30;;;;4221:338;;4172:7;;4221:338;;4255:16;;4289:15;4515:30;4221:338;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;4221:338:36;;;4198:371;;;;;;4191:378;;4107:469;;;:::o;4582:98::-;441:6;4582:98;:::o;229:421:42:-;287:7;527:6;523:45;;-1:-1:-1;556:1:42;549:8;;523:45;590:5;;;594:1;590;:5;:1;613:5;;;;;:10;605:19;;;;;;642:1;229:421;-1:-1:-1;;;229:421:42:o;778:296::-;836:7;933:1;929;:5;921:14;;;;;;945:9;961:1;957;:5;;;;;;;778:296;-1:-1:-1;;;;778:296:42:o;1205:145::-;1263:7;1295:1;1290;:6;;1282:15;;;;;;-1:-1:-1;1319:5:42;;;1205:145::o;2486:435:36:-;2599:1;2578:5;:18;;;:22;2557:88;;;;-1:-1:-1;;;2557:88:36;;;;;;;;;2699:1;2676:5;:20;;;:24;:65;;;;;441:6;2704:5;:20;;;:37;2676:65;2655:135;;;;-1:-1:-1;;;2655:135:36;;;;;;;;;2808:15;;;;-1:-1:-1;;;;;2808:29:36;2800:60;;;;-1:-1:-1;;;2800:60:36;;;;;;;;;2893:3;2878:5;:12;;;:18;2870:44;;;;-1:-1:-1;;;2870:44:36;;;;;;;;;2486:435;:::o;2072:276::-;2186:4;2206:17;2226:19;2239:5;2226:12;:19::i;:::-;2206:39;;2330:5;:11;;;-1:-1:-1;;;;;2262:79:36;:64;2276:39;2305:9;2276:28;:39::i;:::-;2317:8;2262:13;:64::i;:::-;-1:-1:-1;;;;;2262:79:36;;;2072:276;-1:-1:-1;;;;2072:276:36:o;1431:145:42:-;1489:7;1520:5;;;1543:6;;;;1535:15;;;;;6557:230:14;6711:4;6738:5;;:42;;-1:-1:-1;;;6738:42:14;;:5;;;;-1:-1:-1;;;;;6738:5:14;;:18;;:42;;6757:5;;6764:4;;6770:2;;6774:5;;6738:42;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;6738:42:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6738:42:14;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;6738:42:14;;;;;;;;;6731:49;6557:230;-1:-1:-1;;;;;6557:230:14:o;8419:1185::-;8586:5;:30;;;8582:1016;;;8632:6;;8677:16;;8711:15;;;;8744:11;;;;8821:20;;;;;8632:223;;-1:-1:-1;;;8632:223:14;;-1:-1:-1;;;;;8632:6:14;;;;:27;;:223;;8677:16;;8711:15;;8744:11;;8632:6;;8821:20;8632:223;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;8632:223:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;8869:6:14;;8912:16;;8946:15;;;;8979:11;;;;9056:24;;8869:225;;-1:-1:-1;;;8869:225:14;;-1:-1:-1;;;;;8869:6:14;;;;-1:-1:-1;8869:25:14;;-1:-1:-1;8869:225:14;;:6;;9056:24;8869:225;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;8869:225:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;8869:225:14;;;;8582:1016;;;9125:6;;;9170:16;;9204:15;;;;9237:11;;;;9314:20;;;;;9125:223;;-1:-1:-1;;;9125:223:14;;-1:-1:-1;;;;;9125:6:14;;;;:27;;:223;;9170:16;9204:15;9237:11;9314:20;9125:223;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9125:223:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;9362:6:14;;;9405:16;;9439:15;;;;9472:11;;;;9549:24;;9362:225;;-1:-1:-1;;;9362:225:14;;-1:-1:-1;;;;;9362:6:14;;;;-1:-1:-1;9362:25:14;;-1:-1:-1;9362:225:14;;9405:16;;9439:15;;9472:11;;9362:225;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9362:225:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;9828:413:14;10047:15;;;;10080:11;;;;10117:6;;10142:24;;10013:167;;10047:15;10080:11;-1:-1:-1;;;;;10117:6:14;;10013:16;:167::i;:::-;9992:242;;;;-1:-1:-1;;;9992:242:14;;;;;;;;1785:265:41;1854:7;2037:4;1984:58;;;;;;;;;350:9218:18;;;;;;;;;;;;;;;;;;;;;;;;:::o;5:130:-1:-;72:20;;97:33;72:20;97:33;;158:685;;276:3;269:4;261:6;257:17;253:27;243:2;;-1:-1;;284:12;243:2;331:6;318:20;353:81;368:65;426:6;368:65;;;353:81;;;462:21;;;344:90;-1:-1;506:4;519:14;;;;494:17;;614:1;599:238;624:6;621:1;618:13;599:238;;;731:42;769:3;506:4;707:3;694:17;498:6;682:30;;731:42;;;719:55;;506:4;788:14;;;;816;;;;;646:1;639:9;599:238;;;603:14;;;;236:607;;;;;883:760;;1015:3;1008:4;1000:6;996:17;992:27;982:2;;-1:-1;;1023:12;982:2;1070:6;1057:20;1092:95;1107:79;1179:6;1107:79;;1092:95;1215:21;;;1083:104;-1:-1;1259:4;1272:14;;;;1247:17;;;1373:6;1361:19;;;1352:29;;;;1349:38;-1:-1;1346:2;;;1400:1;;1390:12;1346:2;1425:1;1410:227;1435:6;1432:1;1429:13;1410:227;;;1373:6;8162:9;8157:3;8153:19;8149:32;8146:2;;;1425:1;;8184:12;8146:2;8212:22;1373:6;8212:22;;;8343;2709:20;8304:16;8297:75;8471:49;8516:3;1259:4;8496:9;8492:22;8471:49;;;1259:4;8457:5;8453:16;8446:75;8590:2;8648:9;8644:22;9673:20;8590:2;8609:5;8605:16;8598:75;8744:2;8802:9;8798:22;9673:20;8744:2;8763:5;8759:16;8752:75;8890:3;8949:9;8945:22;9673:20;8890:3;8910:5;8906:16;8899:75;9035:3;9094:9;9090:22;9673:20;9035:3;9055:5;9051:16;9044:75;9215:49;9260:3;9181;9240:9;9236:22;9215:49;;;9181:3;9201:5;9197:16;9190:75;9364:49;9409:3;9330;9389:9;9385:22;9364:49;;;9330:3;9350:5;9346:16;9339:75;9495:3;9531:46;9573:3;9495;9553:9;9549:22;9531:46;;;9511:18;;;9504:74;1503:69;;1586:14;;;;1614:16;;;;1457:1;1450:9;1410:227;;;1414:14;;;;;;975:668;;;;;1669:699;;1782:3;1775:4;1767:6;1763:17;1759:27;1749:2;;-1:-1;;1790:12;1749:2;1837:6;1824:20;1859:76;1874:60;1927:6;1874:60;;1859:76;1963:21;;;1850:85;-1:-1;2007:4;2020:14;;;;1995:17;;;2109;;;2100:27;;;;2097:36;-1:-1;2094:2;;;2146:1;;2136:12;2094:2;2171:1;2156:206;2181:6;2178:1;2175:13;2156:206;;;9673:20;;2249:50;;2313:14;;;;2341;;;;2203:1;2196:9;2156:206;;;2160:14;;;;;1742:626;;;;;2376:124;2440:20;;2465:30;2440:20;2465:30;;2921:432;;3018:3;3011:4;3003:6;2999:17;2995:27;2985:2;;-1:-1;;3026:12;2985:2;3073:6;3060:20;49885:18;49877:6;49874:30;49871:2;;;-1:-1;;49907:12;49871:2;3095:60;49980:9;49961:17;;-1:-1;;49957:33;50048:4;50038:15;3095:60;;;3086:69;;3175:6;3168:5;3161:21;3279:3;50048:4;3270:6;3203;3261:16;;3258:25;3255:2;;;3296:1;;3286:12;3255:2;54859:6;50048:4;3203:6;3199:17;50048:4;3237:5;3233:16;54836:30;54915:1;54897:16;;;50048:4;54897:16;54890:27;3237:5;2978:375;-1:-1;;2978:375;5003:1870;;5121:4;5109:9;5104:3;5100:19;5096:30;5093:2;;;-1:-1;;5129:12;5093:2;5157:20;5121:4;5157:20;;;5148:29;;5242:17;5229:31;5280:18;;5272:6;5269:30;5266:2;;;5257:1;;5302:12;5266:2;5347:55;5398:3;5389:6;5378:9;5374:22;5347:55;;;5329:16;5322:81;5494:2;5483:9;5479:18;5466:32;5452:46;;5280:18;5510:6;5507:30;5504:2;;;5257:1;;5540:12;5504:2;5585:55;5636:3;5627:6;5616:9;5612:22;5585:55;;;5494:2;5571:5;5567:16;5560:81;5733:2;5722:9;5718:18;5705:32;5691:46;;5280:18;5749:6;5746:30;5743:2;;;5257:1;;5779:12;5743:2;5824:55;5875:3;5866:6;5855:9;5851:22;5824:55;;;5733:2;5810:5;5806:16;5799:81;5970:2;5959:9;5955:18;5942:32;5928:46;;5280:18;5986:6;5983:30;5980:2;;;5257:1;;6016:12;5980:2;6061:55;6112:3;6103:6;6092:9;6088:22;6061:55;;;5970:2;6047:5;6043:16;6036:81;6206:3;6195:9;6191:19;6178:33;6164:47;;5280:18;6223:6;6220:30;6217:2;;;5257:1;;6253:12;6217:2;6298:55;6349:3;6340:6;6329:9;6325:22;6298:55;;;6206:3;6284:5;6280:16;6273:81;6448:3;6437:9;6433:19;6420:33;6406:47;;5280:18;6465:6;6462:30;6459:2;;;5257:1;;6495:12;6459:2;6540:55;6591:3;6582:6;6571:9;6567:22;6540:55;;;6448:3;6526:5;6522:16;6515:81;6686:3;6675:9;6671:19;6658:33;6644:47;;5280:18;6703:6;6700:30;6697:2;;;5257:1;;6733:12;6697:2;;6778:73;6847:3;6838:6;6827:9;6823:22;6778:73;;;6686:3;6764:5;6760:16;6753:99;;5087:1786;;;;;6913:1118;;7026:4;7014:9;7009:3;7005:19;7001:30;6998:2;;;-1:-1;;7034:12;6998:2;7062:20;7026:4;7062:20;;;7053:29;;7147:17;7134:31;7185:18;;7177:6;7174:30;7171:2;;;7162:1;;7207:12;7171:2;7252:89;7337:3;7328:6;7317:9;7313:22;7252:89;;;7234:16;7227:115;7436:2;7425:9;7421:18;7408:32;7394:46;;7185:18;7452:6;7449:30;7446:2;;;7162:1;;7482:12;7446:2;7527:75;7598:3;7589:6;7578:9;7574:22;7527:75;;;7436:2;7513:5;7509:16;7502:101;7700:2;7689:9;7685:18;7672:32;7658:46;;7185:18;7716:6;7713:30;7710:2;;;7162:1;;7746:12;7710:2;;7791:70;7857:3;7848:6;7837:9;7833:22;7791:70;;;7700:2;7777:5;7773:16;7766:96;;7927:2;7985:9;7981:22;9673:20;7927:2;7946:5;7942:16;7935:75;6992:1039;;;;;9884:257;;9996:2;9984:9;9975:7;9971:23;9967:32;9964:2;;;-1:-1;;10002:12;9964:2;2588:6;2582:13;2600:30;2624:5;2600:30;;10148:263;;10263:2;10251:9;10242:7;10238:23;10234:32;10231:2;;;-1:-1;;10269:12;10231:2;-1:-1;2857:13;;10225:186;-1:-1;10225:186;10418:785;;;;;10657:3;10645:9;10636:7;10632:23;10628:33;10625:2;;;-1:-1;;10664:12;10625:2;4074:6;4061:20;4086:48;4128:5;4086:48;;;10716:78;-1:-1;10831:2;10886:22;;3893:20;3918:49;3893:20;3918:49;;;10839:79;-1:-1;10955:2;11022:22;;4428:20;4453:61;4428:20;4453:61;;;10963:91;-1:-1;11091:2;11155:22;;4238:20;4263:58;4238:20;4263:58;;;10619:584;;;;-1:-1;10619:584;;-1:-1;;10619:584;11210:969;;;;;11412:3;11400:9;11391:7;11387:23;11383:33;11380:2;;;-1:-1;;11419:12;11380:2;11477:17;11464:31;11515:18;;11507:6;11504:30;11501:2;;;-1:-1;;11537:12;11501:2;11567:82;11641:7;11632:6;11621:9;11617:22;11567:82;;;11557:92;;11686:2;11729:9;11725:22;72:20;63:29;;97:33;124:5;97:33;;;11694:63;;-1:-1;11822:2;11807:18;;11794:32;;11835:30;;;11832:2;;;-1:-1;;11868:12;11832:2;11898:62;11952:7;11943:6;11932:9;11928:22;11898:62;;;11888:72;;12025:2;12014:9;12010:18;11997:32;11983:46;;11515:18;12041:6;12038:30;12035:2;;;-1:-1;;12071:12;12035:2;;12101:62;12155:7;12146:6;12135:9;12131:22;12101:62;;;12091:72;;;11374:805;;;;;;;;12186:614;;;12345:2;12333:9;12324:7;12320:23;12316:32;12313:2;;;-1:-1;;12351:12;12313:2;12409:17;12396:31;12447:18;;12439:6;12436:30;12433:2;;;-1:-1;;12469:12;12433:2;12499:82;12573:7;12564:6;12553:9;12549:22;12499:82;;;12489:92;;12646:2;12635:9;12631:18;12618:32;12604:46;;12447:18;12662:6;12659:30;12656:2;;;-1:-1;;12692:12;12656:2;;12722:62;12776:7;12767:6;12756:9;12752:22;12722:62;;;12712:72;;;12307:493;;;;;;15889:654;;16064:5;51313:12;52385:6;52380:3;52373:19;52422:4;52417:3;52413:14;16076:83;;52422:4;16226:5;50839:14;-1:-1;16265:256;16290:6;16287:1;16284:13;16265:256;;;16351:13;;16971:37;;52422:4;13681:14;;;;51992;;;;16312:1;16305:9;16265:256;;;-1:-1;16527:10;;15999:544;-1:-1;;;;15999:544;16551:94;53627:13;53620:21;16606:34;;16600:45;17299:315;;17423:5;51313:12;52385:6;52380:3;52373:19;-1:-1;55004:101;55018:6;55015:1;55012:13;55004:101;;;52422:4;55085:11;;;;;55079:18;55066:11;;;;;55059:39;55033:10;55004:101;;;55120:6;55117:1;55114:13;55111:2;;;-1:-1;52422:4;55176:6;52417:3;55167:16;;55160:27;55111:2;-1:-1;49980:9;55828:14;-1:-1;;55824:28;17570:39;;;;52422:4;17570:39;;17375:239;-1:-1;;17375:239;26407:1168;26618:23;;26550:4;26654:38;;;51313:12;;26541:14;;;52373:19;;;26407:1168;;52422:4;;26407:1168;;52413:14;;;;51313:12;50839:14;;15515:313;15540:6;15537:1;15534:13;15515:313;;;13389:88;13473:3;15607:6;15601:13;13389:88;;;15562:1;15555:9;;;;;13506:6;13497:16;;;;;51992:14;;15515:313;;;-1:-1;;26923:16;;;26917:23;26976:14;;;26960;;;26953:38;51313:12;;52373:19;;;-1:-1;;;52413:14;;;;14468:17;;;14459:27;;;;;50839:14;;14597:341;14622:6;14619:1;14616:13;14597:341;;;49980:9;;52417:3;14678:4;14674:20;;14669:3;14662:33;13189:60;13245:3;14729:6;14723:13;13189:60;;;15562:1;14637:9;;;;;14917:14;;;;14743:82;-1:-1;51992:14;;14597:341;;;14601:14;27208:4;27201:5;27197:16;27191:23;27171:43;;27260:3;27254:4;27250:14;27208:4;27238:3;27234:14;27227:38;27280:99;27374:4;27360:12;27280:99;;;27272:107;;;;;;27468:4;27461:5;27457:16;27451:23;27468:4;27532:3;27528:14;16971:37;27559:11;;;;;26523:1052;;;;;27663:657;27889:23;;16971:37;;28067:4;28056:16;;;28050:23;28127:14;;;16971:37;28224:4;28213:16;;;28207:23;28284:14;;16971:37;27789:531;28380:1606;28599:16;28593:23;16978:3;16971:37;28769:4;28762:5;28758:16;28752:23;49885:18;;54418:42;;;;54411:5;54407:54;28769:4;28833:3;28829:14;13770:37;28931:4;28924:5;28920:16;28914:23;28931:4;28995:3;28991:14;16971:37;29095:4;29088:5;29084:16;29078:23;29095:4;29159:3;29155:14;16971:37;29251:4;29244:5;29240:16;29234:23;29251:4;29315:3;29311:14;16971:37;29405:4;29398:5;29394:16;29388:23;29405:4;29469:3;29465:14;16971:37;54418:42;29560:4;29553:5;29549:16;29543:23;54407:54;29560:4;29624:3;29620:14;13770:37;54418:42;29718:4;29711:5;29707:16;29701:23;54407:54;29718:4;29782:3;29778:14;13770:37;;;29892:6;;29885:5;29881:18;29875:25;29906:59;29892:6;29952:3;29948:16;29934:12;29906:59;;33810:1343;16971:37;;;-1:-1;;56043:2;56039:14;;;;;34244:2;34235:12;;14028:58;34346:12;;;16971:37;;;;34457:12;;;16971:37;;;;34568:12;;;16971:37;;;;34679:12;;;16971:37;;;;56039:14;;;;34790:12;;;14028:58;56039:14;;;;34901:12;;;14028:58;53627:13;53620:21;55940:3;55936:15;35012:12;;;16846:52;35117:11;;;34135:1018;35160:511;19054:66;19034:87;;19018:2;19140:12;;16971:37;;;;35634:12;;;35368:303;35678:213;-1:-1;;;;;54407:54;;;;13770:37;;35796:2;35781:18;;35767:124;35898:547;-1:-1;;;;;54407:54;;;13770:37;;54407:54;;;36265:2;36250:18;;13770:37;54407:54;;36348:2;36333:18;;13770:37;36431:2;36416:18;;16971:37;;;;36100:3;36085:19;;36071:374;36452:201;53627:13;;53620:21;16606:34;;36564:2;36549:18;;36535:118;36660:213;16971:37;;;36778:2;36763:18;;36749:124;36880:679;16971:37;;;-1:-1;;;;;54407:54;;;37285:2;37270:18;;13770:37;54407:54;;37368:2;37353:18;;13770:37;37120:3;37105:19;;56152:1;56142:12;;56132:2;;56158:9;56132:2;37461;37446:18;;17702:60;;;;37544:3;37529:19;16971:37;37091:468;;-1:-1;;;37091:468;37566:539;16971:37;;;54623:4;54612:16;;;;37925:2;37910:18;;33763:35;38008:2;37993:18;;16971:37;38091:2;38076:18;;16971:37;37764:3;37749:19;;37735:370;38112:407;38303:2;38317:47;;;18325:2;38288:18;;;52373:19;-1:-1;;;52413:14;;;18341:43;18403:12;;;38274:245;38526:407;38717:2;38731:47;;;18654:2;38702:18;;;52373:19;-1:-1;;;52413:14;;;18670:42;18731:12;;;38688:245;38940:407;39131:2;39145:47;;;19391:2;39116:18;;;52373:19;19427:27;52413:14;;;19407:48;19474:12;;;39102:245;39354:407;39545:2;39559:47;;;19725:2;39530:18;;;52373:19;-1:-1;;;52413:14;;;19741:42;19802:12;;;39516:245;39768:407;39959:2;39973:47;;;20053:2;39944:18;;;52373:19;-1:-1;;;52413:14;;;20069:41;20129:12;;;39930:245;40182:407;40373:2;40387:47;;;20380:2;40358:18;;;52373:19;20416:25;52413:14;;;20396:46;20461:12;;;40344:245;40596:407;40787:2;40801:47;;;20712:2;40772:18;;;52373:19;20748:25;52413:14;;;20728:46;20793:12;;;40758:245;41010:407;41201:2;41215:47;;;21044:2;41186:18;;;52373:19;-1:-1;;;52413:14;;;21060:40;21119:12;;;41172:245;41424:407;41615:2;41629:47;;;21370:2;41600:18;;;52373:19;-1:-1;;;52413:14;;;21386:45;21450:12;;;41586:245;41838:407;42029:2;42043:47;;;21701:2;42014:18;;;52373:19;21737:25;52413:14;;;21717:46;21782:12;;;42000:245;42252:407;42443:2;42457:47;;;22033:2;42428:18;;;52373:19;22069:26;52413:14;;;22049:47;22115:12;;;42414:245;42666:407;42857:2;42871:47;;;22366:2;42842:18;;;52373:19;-1:-1;;;52413:14;;;22382:36;22437:12;;;42828:245;43080:407;43271:2;43285:47;;;22688:2;43256:18;;;52373:19;-1:-1;;;52413:14;;;22704:41;22764:12;;;43242:245;43494:407;43685:2;43699:47;;;23015:2;43670:18;;;52373:19;-1:-1;;;52413:14;;;23031:41;23091:12;;;43656:245;43908:407;44099:2;44113:47;;;23342:2;44084:18;;;52373:19;-1:-1;;;52413:14;;;23358:45;23422:12;;;44070:245;44322:407;44513:2;44527:47;;;23673:2;44498:18;;;52373:19;-1:-1;;;52413:14;;;23689:38;23746:12;;;44484:245;44736:407;44927:2;44941:47;;;23997:2;44912:18;;;52373:19;24033:29;52413:14;;;24013:50;24082:12;;;44898:245;45150:407;45341:2;45355:47;;;24333:2;45326:18;;;52373:19;24369:30;52413:14;;;24349:51;24419:12;;;45312:245;45564:377;;45740:2;45761:17;45754:47;24743:16;24737:23;24669:4;45740:2;45729:9;45725:18;24773:38;24826:69;24660:14;45729:9;24660:14;24876:12;24826:69;;;45740:2;24975:5;24971:16;24965:23;24945:43;;49980:9;;25024:14;45729:9;25028:4;25024:14;;25008;45729:9;25008:14;25001:38;25054:69;25118:4;25104:12;25054:69;;;25008:14;25204:5;25200:16;25194:23;25174:43;;25024:14;45729:9;25257:4;25253:14;;25237;45729:9;25237:14;25230:38;25283:69;25347:4;25333:12;25283:69;;;25275:77;;;25237:14;25431:5;25427:16;25421:23;25401:43;;25024:14;45729:9;25484:4;25480:14;;25464;45729:9;25464:14;25457:38;25510:69;25574:4;25560:12;25510:69;;;25464:14;25657:5;25653:16;25647:23;25627:43;;25024:14;45729:9;25710:4;25706:14;;25690;45729:9;25690:14;25683:38;25736:69;25800:4;25786:12;25736:69;;;25728:77;;;25690:14;25888:5;25884:16;25878:23;25858:43;;25024:14;45729:9;25941:4;25937:14;;25921;45729:9;25921:14;25914:38;25967:69;26031:4;26017:12;25967:69;;;25921:14;26115:5;26111:16;26105:23;26085:43;;25024:14;45729:9;26168:4;26164:14;;24669:4;45729:9;26148:14;26141:38;26194:105;26294:4;26280:12;26194:105;;;45807:124;45711:230;-1:-1;;;;;;;45711:230;45948:418;46140:3;46125:19;;46155:117;46129:9;46245:6;46155:117;;;17001:5;46351:3;46340:9;46336:19;16971:37;46111:255;;;;;;46790:871;16971:37;;;47291:2;47276:18;;16971:37;;;47374:2;47359:18;;16971:37;;;47126:3;47111:19;;47389:118;47503:2;47488:18;;47479:6;47389:118;;;47518:133;47646:3;47635:9;47631:19;47622:6;47518:133;;;47097:564;;;;;;;;;48538:256;48600:2;48594:9;48626:17;;;48701:18;48686:34;;48722:22;;;48683:62;48680:2;;;48758:1;;48748:12;48680:2;48600;48767:22;48578:216;;-1:-1;48578:216;48801:305;;48961:18;48953:6;48950:30;48947:2;;;-1:-1;;48983:12;48947:2;-1:-1;49028:4;49016:17;;;49081:15;;48884:222;56181:117;-1:-1;;;;;54407:54;;56240:35;;56230:2;;56289:1;;56279:12;56305:111;56386:5;53627:13;53620:21;56364:5;56361:32;56351:2;;56407:1;;56397:12

Swarm Source

bzzr://af59bc471fef2ae8427d4dcfc1cce3d5f11d7b83e8d4a51016d4186688de536f

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.