NAV Navbar
solidity
  • Introduction
  • dApp
  • Solidity Smart Contracts
  • MARKET.js
  • FAQ - General
  • FAQ - MARKET Protocol
  • FAQ - Solidity Smart Contracts
  • FAQ - API
  • FAQ - dApp
  • Getting help
  • Contributing
  • Bug Reporting
  • Introduction

    Welcome to MARKET Protocol documentation here you will find documentation for our smart contracts and APIs.

    MARKET Protocol has been created to provide a secure, flexible, open source foundation for decentralized trading on the Ethereum blockchain. We provide the pieces necessary to create a decentralized exchange, including the requisite clearing and collateral pool infrastructure, enabling third parties to build applications for trading.

    Visit our Github: https://github.com/MARKETProtocol

    Trade Flow

    Documentation

    Frequently Asked Questions

    dApp

    The MARKET Protocol dApp provides tools for contract creation, oracle testing and deployment. Additionally, users are able to easily search previously deployed MARKET contracts they would like to trade.

    A simulated trading environment allows user to place test trades and participate in beta releases of the protocol.

    Our beta dApp is currently running on the Rinkeby testnet here.

    Using an Ethereum-enabled browser

    For testing and interacting with our dApp, you will need to use a browser that supports Web3. We recommend using the Metamask Chrome Browser Extension. This will enable you to connect to the Ethereum network from your browser. Metamask allows you to run Ethereum dApps right in your browser without running a full Ethereum node.

    Acquire Test ETH

    Our smart contracts are currently deployed on the Rinkeby testnet. You will need to have test ETH to use this library. You can request test funds from the Rinkeby faucet.

    Contract Deployment

    MARKET Protocol creates a flexible contract specification which allows users to easily implement their desired contract prior to trading. First time users, can use our Guided Deploy process walking them through the step by step process to deployment. Expert users, can opt for a more condensed process with the Quick Deploy

    Guided Deploy

    MARKET Protocol Guided Deploy provides a step by step guide to first time deployment. Below are the needed variables to deploy a contract to the Ethereum Blockchain

    1. Name - the contract name should be as descriptive as possible capturing the underlying asset relationship as well as possibly the expiration. Something like ETH/BTC-Kraken_YYYY-MM-DD may help others understand the underlying asset, the data source, and expiration date in a nice human readable and searchable way. In the future, MARKET will implement a standardized naming convention and guidelines to formalize this process
    2. Collateral Token - every contract should be backed by an ERC20 Token that will be used a collateral for the contract. Traders must deposit tokens to the smart contract prior to trading, and upon execution of a trade, the appropriate amount of collateral becomes locked until that position is exited. In this fashion, all open positions always remain 100% collateralized removing counter party risk from the traders. Please specify a ERC20 Token address for this contract. In the future, users will be able to easily select from well known ERC20 tokens to ensure more safety and avoid dealing with long addresses.
    3. Oraclize.it data source - Oraclize.it offers several data-sources such as "URL" and "WolframAlpha"
    4. Price Decimal Places - Ethereum currently does not support floating points numbers. Therefore all prices reported by oracles must be converted to a whole number (integer). This variable is how many decimal places one needs to move the decimal in order to go from the oracle query price to an integer. For example, if the oracle query results returned a value of 190.22, we need to move the decimal two (2) places to convert to a whole number of 19022, so we would enter 2.
    5. Price Floor - this is the lower bound of price exposure this contract will trade. If the oracle reports a price below this value the contract will enter into settlement. This should also be represented as a whole number. If we take the example above of a price of 190.22 and decide the Floor for our contract should be 150.00, we would enter 15000.
    6. Price Cap - This is the upper bound of price exposure this contract will trade. If the oracle reports a price above this value the contract will enter into settlement. Following our example, if we decide the Cap for our contract should be 230.00, we would enter 23000 as our Cap.
    7. Qty Multiplier - The quantity multiplier allows the user to specify how many base units (for Ethereum, this would be wei) each integer price movement changes the value of the contract. If our integerized price was 19022 with a qty multiplier of 1, and the price moved to 19023, then the value will have change by 1 wei. If however the multiplier was set at 1,000,000,000 the price movement of 1 unit would now correspond to a value of 1 gwei (not wei). Please see here for an ethereum unit converter.
    8. Expiration Time - upon reaching the expiration timestamp all open positions will settle against the final price query returned by the oracle.

    Quick Deploy

    MARKET Protocol Quick Deploy provides a scaled down interface for easy deployment of contracts to the Ethereum blockchain. Expert users can enter variables, that are validated with error checking prior to deploying.

    Parameter Description
    Name Viewable name of this contract, in the future we will implement suggested naming conventions
    Collateral Token Address address of the ERC20 token that will be used for collateral
    Price Floor minimum tradeable price of this contract
    Price Cap maximum tradeable price of this contract
    Price Decimal Places Since all numbers must be represented as integers on the Ethereum blockchain, this is how many decimal places one needs to move the decimal in order to go from the oracle query price to an integer. For instance if the oracle query results returned a value such as 190.22, we need to move the decimal two (2) places to convert to an integer value of 19022.
    Qty Multiplier The qty multiplier allows the user to specify how many base units (for ethereum, this would be wei) each integer price movement changes the value of the contract. If our integerized price was 19022 with a qty multiplier of 1, and the price moved to 19023, then the value will have change by 1 wei. If however the multiplier was set at 1,000,000,000 the price movement of 1 unit would now correspond to a value of 1 gwei (not wei)
    Expiration Time Expiration timestamp for all open positions to settle.
    Oraclize.it data source Available data sources from Oraclize.it
    Oraclize.it Query Properly structured Oraclize.it query, please use the test query page for clarification

    Explore Contracts

    MARKET Protocol's dApp provides the needed functionality to easily search, filter, and sort already deployed MARKET Smart Contracts.

    Find Contracts

    The Find Contracts screen allows for a reverse lookup for MARKET Contracts using the ethereum address of the deployed contract. Users can enter a known address, if valid, the dApp will display the current specifications of the MARKET Contract deployed to this address.

    Test Query

    Simulated Exchange

    Coming soon...

    Solidity Smart Contracts

    All code for our smart contracts can be found here. If you have any issues to report please do so by opening an issue on GitHub.

    Market Contract

    MarketContract constructor:

    /// @param contractName viewable name of this contract (BTC/ETH, LTC/ETH, etc)
    /// @param creatorAddress address of the person creating the contract
    /// @param marketTokenAddress address of our member token
    /// @param collateralTokenAddress address of the ERC20 token that will be used for collateral and pricing
    /// @param collateralPoolFactoryAddress address of the factory creating the collateral pools
    /// @param contractSpecs array of unsigned integers including:
    /// floorPrice minimum tradeable price of this contract, contract enters settlement if breached
    /// capPrice maximum tradeable price of this contract, contract enters settlement if breached
    /// priceDecimalPlaces number of decimal places to convert our queried price from a floating point to
    /// an integer
    /// qtyMultiplier multiply traded qty by this value from base units of collateral token.
    /// expirationTimeStamp - seconds from epoch that this contract expires and enters settlement
    constructor(
        string contractName,
        address creatorAddress,
        address marketTokenAddress,
        address collateralTokenAddress,
        address collateralPoolFactoryAddress,
        uint[5] contractSpecs
    ) public
    {
        COLLATERAL_POOL_FACTORY_ADDRESS = collateralPoolFactoryAddress;
        MKT_TOKEN_ADDRESS = marketTokenAddress;
        MKT_TOKEN = MarketToken(marketTokenAddress);
        require(MKT_TOKEN.isBalanceSufficientForContractCreation(msg.sender));    // creator must be MKT holder
        PRICE_FLOOR = contractSpecs[0];
        PRICE_CAP = contractSpecs[1];
        require(PRICE_CAP > PRICE_FLOOR);
    
        PRICE_DECIMAL_PLACES = contractSpecs[2];
        QTY_MULTIPLIER = contractSpecs[3];
        EXPIRATION = contractSpecs[4];
        require(EXPIRATION > now);
    
        CONTRACT_NAME = contractName;
        COLLATERAL_TOKEN_ADDRESS = collateralTokenAddress;
        creator = creatorAddress;
    }
    

    The MarketContract represents the main contract responsible for combining needed functionality for trading, settlement and position management. Each MarketContract must be paired with a unique MarketCollateralPool (see below) after instantiation in order to allow trading to become enabled.

    Contract Diagram

    MarketContract is an abstract contract that will allow for implementing classes such as MarketContractOraclize to complete the needed top level functionality around oracle solutions. We intend to expand our offering of oracle solutions offered in the near future.

    Oracle Costs

    The Creator of the MarketContract must pre-fund the contract with enough ETH in order to pay for the gas costs associated with the needed oracle query. Currently from Oraclize.it - the first query for any contract is free, so this need has been removed.

    Parameter Description
    contractName viewable name of this contract, in the future we will implement suggested naming conventions
    marketTokenAddress address of the MKT deployed ERC20 token
    collateralTokenAddress address of the ERC20 token that will be used for collateral
    contractSpecs array of unsigned integers including the below parameters
    floorPrice minimum tradeable price of this contract
    capPrice maximum tradeable price of this contract
    expirationTimeStamp seconds from epoch that this contract expires and enters settlement

    Market Contract Oraclize

    MarketContractOraclize constructor:

    /// @param contractName viewable name of this contract (BTC/ETH, LTC/ETH, etc)
    /// @param creatorAddress address of the person creating the contract
    /// @param marketTokenAddress address of our member token
    /// @param collateralTokenAddress address of the ERC20 token that will be used for collateral and pricing
    /// @param collateralPoolFactoryAddress address of the factory creating the collateral pools
    /// @param contractSpecs array of unsigned integers including:
    /// floorPrice minimum tradeable price of this contract, contract enters settlement if breached
    /// capPrice maximum tradeable price of this contract, contract enters settlement if breached
    /// priceDecimalPlaces number of decimal places to convert our queried price from a floating point to
    /// an integer
    /// qtyMultiplier multiply traded qty by this value from base units of collateral token.
    /// expirationTimeStamp - seconds from epoch that this contract expires and enters settlement
    /// @param oracleDataSource a data-source such as "URL", "WolframAlpha", "IPFS"
    /// see http://docs.oraclize.it/#ethereum-quick-start-simple-query
    /// @param oracleQuery see http://docs.oraclize.it/#ethereum-quick-start-simple-query for examples
    constructor(
        string contractName,
        address creatorAddress,
        address marketTokenAddress,
        address collateralTokenAddress,
        address collateralPoolFactoryAddress,
        uint[5] contractSpecs,
        string oracleDataSource,
        string oracleQuery
    ) MarketContract(
        contractName,
        creatorAddress,
        marketTokenAddress,
        collateralTokenAddress,
        collateralPoolFactoryAddress,
        contractSpecs
    )  public
    {
        oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);
        ORACLE_DATA_SOURCE = oracleDataSource;
        ORACLE_QUERY = oracleQuery;
        require(EXPIRATION > now);         // Require expiration time in the future.
    
        // Future timestamp must be within 60 days from now.
        // https://docs.oraclize.it/#ethereum-quick-start-schedule-a-query-in-the-future
        uint secondsPerSixtyDays = 60 * 60 * 24 * 60;
        require(EXPIRATION - now <= secondsPerSixtyDays);
        queryOracle();                      // Schedule a call to oracle at contract expiration time.
    }
    

    MarketContractOraclize is the first fully implemented MarketContract that has been built out. Using Oraclize.it allows for several different sources of truth in order to settle contracts. More information on forming correct queries can be found in their documentation.

    Our dApp additionally has some help in formatting your queries correctly and a test environment to ensure the queries are correct prior to contract deployment.

    Additional parameters

    Parameter Description
    oracleDataSource a data-source such as "URL", "WolframAlpha", "IPFS"
    oracleQuery properly formatted Oraclize.it query

    Market Collateral Pool

    MarketCollateralPool constructor:

    /// @dev instantiates a collateral pool that is unique to the supplied address of a MarketContract. This pairing
    /// is 1:1
    /// @param marketContractAddress deployed address of a MarketContract
    constructor(address marketContractAddress) Linkable(marketContractAddress) public {
        MKT_CONTRACT = MarketContract(marketContractAddress);
        MKT_TOKEN_ADDRESS = MKT_CONTRACT.MKT_TOKEN_ADDRESS();
    }
    

    The MarketCollateralPool is a contract controlled by a specific MarketContract. It holds users balances, locked collateral balances and open positions accounting. These balances and positions are unique to the linked MarketContract and a user must deposit funds for each MarketContract they intend to trade. The ERC20 Token specified are the only accepted form of funding or collateralization.

    Factory deployment

    MarketContractOraclize factory for deployment:

    /// @dev Deploys a new instance of a market contract and adds it to the whitelist.
    /// @param contractName viewable name of this contract (BTC/ETH, LTC/ETH, etc)
    /// @param collateralTokenAddress address of the ERC20 token that will be used for collateral and pricing
    /// @param contractSpecs array of unsigned integers including:
    /// floorPrice minimum tradeable price of this contract, contract enters settlement if breached
    /// capPrice maximum tradeable price of this contract, contract enters settlement if breached
    /// priceDecimalPlaces number of decimal places to convert our queried price from a floating point to
    /// an integer
    /// qtyMultiplier multiply traded qty by this value from base units of collateral token.
    /// expirationTimeStamp - seconds from epoch that this contract expires and enters settlement
    /// @param oracleDataSource a data-source such as "URL", "WolframAlpha", "IPFS"
    /// see http://docs.oraclize.it/#ethereum-quick-start-simple-query
    /// @param oracleQuery see http://docs.oraclize.it/#ethereum-quick-start-simple-query for examples
    function deployMarketContractOraclize(
        string contractName,
        address collateralTokenAddress,
        uint[5] contractSpecs,
        string oracleDataSource,
        string oracleQuery
    ) external
    {
        MarketContractOraclize mktContract = new MarketContractOraclize(
            contractName,
            msg.sender,
            MKT_TOKEN_ADDRESS,
            collateralTokenAddress,
            collateralPoolFactoryAddress,
            contractSpecs,
            oracleDataSource,
            oracleQuery
        );
        MarketContractRegistryInterface(marketContractRegistry).addAddressToWhiteList(mktContract);
        emit MarketContractCreated(address(mktContract));
    }
    

    MarketCollateralPool factory for deployment:

    /// @dev creates the needed collateral pool and links it to our market contract.
    /// @param marketContractAddress address of the newly deployed market contract.
    function deployMarketCollateralPool(address marketContractAddress) external {
        require(MarketContractRegistryInterface(marketContractRegistry).isAddressWhiteListed(marketContractAddress));
        MarketCollateralPool marketCollateralPool = new MarketCollateralPool(marketContractAddress);
        MarketContract(marketContractAddress).setCollateralPoolContractAddress(marketCollateralPool);
    }
    

    Currently two factories exist to aid in the deployment of linked contracts and the whitelisting of these contracts in the MarketContractRegistry, which holds a record of all currently deployed and functional contracts.

    MarketContractOraclize deployment

    First, a user calls deployMarketContractOraclize on the MarketContractFactoryOraclize in order to begin the deployment process.

    This function call creates the new MarketContractOraclize and then adds the address to the MarketContractRegistry so that others may find the contract for trading. A second call to the deployMarketCollateralPool of the MarketCollateralPoolFactory then deploys the needed MarketCollateralPool and links it to the MarketContract. At this point the contract is ready to be traded.

    Collateral

    Depositing funds for trading

    depositTokensForTrading function

    /// @notice deposits tokens to the smart contract to fund the user account and provide needed tokens for collateral
    /// pool upon trade matching.
    /// @param depositAmount qty of ERC20 tokens to deposit to the smart contract to cover open orders and collateral
    function depositTokensForTrading(uint256 depositAmount) external {
        // user must call approve!
        require(MarketToken(MKT_TOKEN_ADDRESS).isUserEnabledForContract(MKT_CONTRACT, msg.sender));
        uint256 balanceAfterDeposit = userAddressToAccountBalance[msg.sender].add(depositAmount);
        ERC20(MKT_CONTRACT.COLLATERAL_TOKEN_ADDRESS()).safeTransferFrom(msg.sender, this, depositAmount);
        userAddressToAccountBalance[msg.sender] = balanceAfterDeposit;
        emit UpdatedUserBalance(msg.sender, balanceAfterDeposit);
    }
    

    Funds deposited by a user are allocated to their address's account balance until a point at which a new position is opened and the funds then become allocated to collateralPoolBalance and are locked until the user exits their position or the contract expires. In this way, all open positions are always fully collateralized eliminating any counter party risk and ensuring the solvency of the contract.

    Calculating needed collateral and maximum possible loss

    calculateNeededCollateral function

    /// @notice determines the amount of needed collateral for a given position (qty and price)
    /// @param priceFloor lowest price the contract is allowed to trade before expiration
    /// @param priceCap highest price the contract is allowed to trade before expiration
    /// @param qtyMultiplier multiplier for qty from base units
    /// @param qty signed integer corresponding to the traded quantity
    /// @param price of the trade
    function calculateNeededCollateral(
        uint priceFloor,
        uint priceCap,
        uint qtyMultiplier,
        int qty,
        uint price
    ) pure internal returns (uint neededCollateral)
    {
    
        uint maxLoss;
        if (qty > 0) {   // this qty is long, calculate max loss from entry price to floor
            if (price <= priceFloor) {
                maxLoss = 0;
            } else {
                maxLoss = subtract(price, priceFloor);
            }
        } else { // this qty is short, calculate max loss from entry price to ceiling;
            if (price >= priceCap) {
                maxLoss = 0;
            } else {
                maxLoss = subtract(priceCap, price);
            }
        }
        neededCollateral = maxLoss * abs(qty) * qtyMultiplier;
    }
    

    The amount of funds that are allocated to the collateralPoolBalance upon entering a trade is defined by that positions maximum possible loss.

    All positions are always fully collateralized, meaning the maximum possible loss for a position is the required amount of collateral to open that position. This can be calculated from the price and qty of the position and the defined specifications of the MarketContract.

    For a buyer, the maximum possible loss is calculated as the price of the trade minus the priceFloor times the qty transacted. Conversely, if you are opening a short position the maximum loss is calculated as priceCap minus the price of the trade, multiplied by the qty transacted. Upon filling an order both parties commit their respective maximum loss to the collateral pool.

    Parameter Description
    priceFloor as defined in the MarketContract
    priceCap as defined in the MarketContract
    qtyMultiplier as defined in the MarketContract
    qty signed integer corresponding to the traded quantity
    price agreed upon execution price

    Withdrawing funds

    withdrawTokens function

    /// @notice removes token from users trading account
    /// @param withdrawAmount qty of token to attempt to withdraw
    function withdrawTokens(uint256 withdrawAmount) public {
        //require(userAddressToAccountBalance[msg.sender] >= withdrawAmount);  subtract call below will enforce this
        uint256 balanceAfterWithdrawal = userAddressToAccountBalance[msg.sender].subtract(withdrawAmount);
        userAddressToAccountBalance[msg.sender] = balanceAfterWithdrawal;   // update balance before external call!
        ERC20(MKT_CONTRACT.COLLATERAL_TOKEN_ADDRESS()).safeTransfer(msg.sender, withdrawAmount);
        emit UpdatedUserBalance(msg.sender, balanceAfterWithdrawal);
    }
    

    At any time, tokens that are not allocated to an open position held by the user, are able to be withdrawn.

    Upon exiting a position funds are returned to the user's account balance, net of any profit or loss. Similarly, if the contract expires with the user maintaining an open position, their position settles to the final settlement price of the contract and funds are then eligible for immediate withdraw.

    Orders

    MARKET's Order struct

    struct Order {
        address maker;
        address taker;
        address feeRecipient;
        uint makerFee;
        uint takerFee;
        uint price;
        uint expirationTimeStamp;
        int qty;
        bytes32 orderHash;
    }
    

    Generating and confirming Order signatures

    /// @notice creates the hash for the given order parameters.
    /// @param contractAddress address of the calling contract, orders are unique to each contract
    /// @param orderAddresses array of 3 address. maker, taker, and feeRecipient
    /// @param unsignedOrderValues array of 5 unsigned integers. makerFee, takerFee, price, expirationTimeStamp and salt
    /// @param orderQty signed qty of the original order.
    function createOrderHash(
        address contractAddress,
        address[3] orderAddresses,
        uint[5] unsignedOrderValues,
        int orderQty
    ) public pure returns (bytes32)
    {
        return keccak256(
            abi.encodePacked(
                contractAddress,
                orderAddresses[0],
                orderAddresses[1],
                orderAddresses[2],
                unsignedOrderValues[0],
                unsignedOrderValues[1],
                unsignedOrderValues[2],
                unsignedOrderValues[3],
                unsignedOrderValues[4],
                orderQty
            )
        );
    }
    
    /// @notice confirms hash originated from signer
    /// @param signerAddress - address of order originator
    /// @param hash - original order hash
    /// @param v order signature
    /// @param r order signature
    /// @param s order signature
    function isValidSignature(
        address signerAddress,
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public pure returns (bool)
    {
        return signerAddress == ecrecover(
            keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)),
            v,
            r,
            s
        );
    }
    

    MARKET utilizes off chain orders to reduce the number of needed transactions that must occur on the blockchain. Third party Nodes will provide order book hosting and aggregation services on top of the protocol to facilitate liquidity. Orders however are cryptographically signed to ensure no manipulation and facilitate trust-less executions.

    Makers create orders and sign them (making liquidity), while takers select signed orders to trade against (taking liquidity).

    Parameter Description
    maker address of user who originated and signed this order
    taker address of counter-party to fill order or null to allow any counter-party
    feeRecipient address of fee recipient node, if any (MARKET does not charge any fees, but nodes may)
    makerFee fee to paid by the maker in MKT tokens to the feeRecipient
    takerFee fee to paid by the taker in MKT tokens to the feeRecipient
    price agreed upon execution price
    expirationTimeStamp timestamp that the order is valid until
    qty agreed upon execution qty
    orderHash hash created by maker to ensure all order parameters are valid and originated from maker

    A maker creates an order with the specified parameters and calls createOrderHash that is transmitted along with the order. Any part can verify the veracity of the hash with isValidSignature which will match the signer's address if all parameters of the order are valid.

    Makers may cancel an order at any time, unfortunately this transaction happens on chain and will require gas to complete. Alternatively, an Order can be created with an expirationTimeStamp expiring the order automatically without the additional gas cost.

    Trading

    // @notice called by a participant wanting to trade a specific order
    /// @param orderAddresses - maker, taker and feeRecipient addresses
    /// @param unsignedOrderValues makerFee, takerFree, price, expirationTimeStamp, and salt (for hashing)
    /// @param orderQty quantity of the order
    /// @param qtyToFill quantity taker is willing to fill of original order(max)
    /// @param v order signature
    /// @param r order signature
    /// @param s order signature
    function tradeOrder(
        address[3] orderAddresses,
        uint[5] unsignedOrderValues,
        int orderQty,
        int qtyToFill,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (int filledQty)
    {
        require(isCollateralPoolContractLinked && !isSettled); // no trading past settlement
        require(orderQty != 0 && qtyToFill != 0 && orderQty.isSameSign(qtyToFill));   // no zero trades, sings match
        require(MKT_TOKEN.isUserEnabledForContract(this, msg.sender));
        OrderLib.Order memory order = address(this).createOrder(orderAddresses, unsignedOrderValues, orderQty);
        require(MKT_TOKEN.isUserEnabledForContract(this, order.maker));
    
        // taker can be anyone, or specifically the caller!
        require(order.taker == address(0) || order.taker == msg.sender);
        // do not allow self trade
        require(order.maker != address(0) && order.maker != msg.sender);
        require(
            order.maker.isValidSignature(
                order.orderHash,
                v,
                r,
                s
        ));
    
    
        if (now >= order.expirationTimeStamp) {
            emit Error(ErrorCodes.ORDER_EXPIRED, order.orderHash);
            return 0;
        }
    
        int remainingQty = orderQty.subtract(getQtyFilledOrCancelledFromOrder(order.orderHash));
        if (remainingQty == 0) { // there is no qty remaining  - cannot fill!
            emit Error(ErrorCodes.ORDER_DEAD, order.orderHash);
            return 0;
        }
    
        filledQty = MathLib.absMin(remainingQty, qtyToFill);
        marketCollateralPool.updatePositions(
            order.maker,
            msg.sender,
            filledQty,
            order.price
        );
        orderMappings.addFilledQtyToOrder(order.orderHash, filledQty);
    
        uint paidMakerFee = 0;
        uint paidTakerFee = 0;
    
        if (order.feeRecipient != address(0)) {
            // we need to transfer fees to recipient
            uint filledAbsQty = filledQty.abs();
            uint orderAbsQty = filledQty.abs();
            if (order.makerFee > 0) {
                paidMakerFee = order.makerFee.divideFractional(filledAbsQty, orderAbsQty);
                MKT_TOKEN.safeTransferFrom(
                    order.maker,
                    order.feeRecipient,
                    paidMakerFee
                );
            }
    
            if (order.takerFee > 0) {
                paidTakerFee = order.takerFee.divideFractional(filledAbsQty, orderAbsQty);
                MKT_TOKEN.safeTransferFrom(
                    msg.sender,
                    order.feeRecipient,
                    paidTakerFee
                );
            }
        }
    
        emit OrderFilled(
            order.maker,
            msg.sender,
            order.feeRecipient,
            filledQty,
            paidMakerFee,
            paidTakerFee,
            order.orderHash
        );
    
        return filledQty;
    }
    

    When a taker finds an order they would like to transact against, they call the tradeOrder function.

    This function, verifies the order signature, ensures all contracts and users are allowed to trade and if successful handles the accounting with the associated resulting fills (either open a new position, or perhaps, closing out an existing open position).

    A taker is not required to fill the entire maker order and specifies the qty they are willing to transact. The price however is static as set and signed by the maker.

    Market Contract Registry

    A registry will exist of all MARKET contracts that are approved for trading. Eventually there will be some mechanism for the community to flag contracts that are not valid, or reasonable for removal from the white list. At first this may be more centralized, but eventually the goal is to have a fully decentralized community in charge of such matters.

    MKT Tokens

    alt text

    MKT Tokens are the lifeblood of the MARKET ecosystem. All fees charged by nodes will be transacted in MKT and additionally anyone who wishes to create a new MarketContract will be forced to have some minimum balance of MKT. Finally, for every MarketContract a user desires to trade, some amount of MKT must be locked to enable access to that contract. These can be unlocked at any time the user wishes to stop trading that MarketContract.

    MARKET.js

    All code for this library can be found here. If you have any issues to report or features to request please do so by opening an issue on GitHub.

    Under Construction

    Order Life Cycle

    Note: this is the generalized lifecycle, function calls will be replaced with MARKET.js function calls that provide a simplified abstraction to the underlying solidity calls.

    1. An order is generated from a maker as described here. Signing and hashing this order allows for us to confirm its validity.
    2. Depending on the application, this order may then be broadcast to a third party order book host who may provide further verifications before publishing the order to their orders books, including:
      • Verifying sufficient funding in the MARKET Contract for the maker's address
      • Validating user has locked MKT to allow for access for trading the specified MARKET Protocol smart contract.
    3. The specified taker, or an arbitrary taker (if none specified) is able to call the traderOrder function filling all or a partial qty of the order. This transaction happens on-chain and therefore validates all aspects of the transaction are successful.
    4. Third party order book hosts will be responsible for removing completely filled or completely cancelled orders from their order books. Orders can be cancelled by setting an expirationTimeStamp or by calling the function cancelOrder at any time

    Requirements for a successful traderOrder call

    In order for a taker to not waste gas on a call to traderOrder that will ultimately fail it is important to note the following requirements in order for a transaction to be executed.

    1. MarketContract must be deployed correctly, linked to a MarketCollateralPool and not be in an isSettled state
    2. Both maker and taker must have locked the requisite amount of MKT to enable trading for the specific contract. This can be verified by calling isUserEnabledForContract in the MarketToken smart contract (not enforced on Rinkeby currently).
    3. caller of tradeOrder is either the specified taker in the order, or no taker was specified
    4. the maker and taker are not the same address (no wash trading)
    5. the order has not expired, been cancelled, nor been completely filled
    6. both maker and taker have sufficient balances to lock collateral for attempted trade

    FAQ - General

    What blockchain is used?

    MARKET Protocol has chosen to build on top of Ethereum.

    What is the token name?

    MARKET Protocol Token

    What is the token ticker symbol?

    MKT

    How can I receive updates from MARKET Protocol?

    Check out our telegram room and join our newsletter!

    What's the total supply of the token?

    600 million MKT tokens (600,000,000)

    Can extra MKT Tokens be added to the total supply?

    No, there is a fixed supply.

    Can you mine the tokens?

    No. All tokens will be minted upon main net launch.

    What wallet should I use to keep my MKT tokens?

    MKT is an ERC20 token, so a wallet that supports ERC20 tokens will be needed.

    When will the main net launch occur?

    The proposed launch date is in Q1 2019

    FAQ - MARKET Protocol

    What is a derivative?

    A derivative represents a contract between a buyer and a seller. The value is derived from on an underlying asset or assets. Common derivatives use stocks, commodities, currencies, bonds, or interest rates as the underlying asset for the contract.

    Are you a decentralized exchange?

    No, MARKET is a protocol to enable the trading of decentralized derivative like contracts. Third parties will write the application layers on top of the protocol and we hope to create an API layer to facilitate this as well.

    Who will host MARKET's order books?

    Third party order book hosts, called nodes will be provided with an API that easy allows them to host an order book. Nodes, in turn may charge fees for the services they provide. These fee's are not determined by MARKET and are set directly by the node.

    Does MARKET charge a fee to use the protocol?

    MARKET doesn't charge any fees. Nodes however may set a fee for their services of hosting order books.

    How is the needed collateral for an open position calculated?

    All positions are always fully collateralized, meaning the maximum possible loss for a position is the required amount of collateral to open that position. For a buyer, the maximum possible loss is calculated as the price of the trade minus the PRICE_FLOOR times the qty transacted. Conversely, if you are opening a short position the maximum loss is calculated as PRICE_CAP minus the price of the trade, multiplied by the qty transacted. Upon filling an order both parties commit their respective maximum loss to the collateral pool.

    If I want to open a short position do I need to borrow the asset?

    No, there is no borrowing, fees to be paid, or locates to deal with for shorting. Due to the unique nature of our derivative like contracts, a trader is able to open a short position without owning the underlying asset. This is similar to how financial futures work, where a seller of the SP500 futures, doesn't need to own, locate, or borrow the SP500 in order to gain the short price exposure to the SP500.

    When is my collateral returned to me and able to be withdrawn?

    Collateral is credited to a users address and able to be withdrawn upon expiration of the contract or if the user trades out of their open position. For instance, if a trader holding a long open position, sells to close out that position prior to expiration, they will immediately be able to withdraw the collateral associated (plus or minus any profit or loss) with their trade.

    What happens if I hold an open position through contract expiration?

    Upon expiration, the contract will reach a settlement price via the agreed upon oracle solution. At this point, all funds will be able to be withdrawn for all open positions. The amount of collateral that is credited back to the user will be determined by their execution price and the settlement price of the contract. Note, that there will probably be some short delay between contract expiration and the settlement period to allow for disputes to be raised.

    When I trade out of an open position, how is my profit or loss allocated?

    When a position is closed, the appropriate amount of funds are allocated back to the user and are immediately available for withdrawal from the smart contract. If the trade that was made was profitable, more funds will be available for withdrawal than originally posted, and if the trade represented a loser for the user, less funds than originally posted would now be available for withdrawal. As an example, let us imagine a contract with a PRICE_FLOOR of 50 and a PRICE_CAP of 150 using Token A as collateral. Bob enters into a long position for a qty of 1 at a price of 85. At this point 35 units of Token A would be committed to the collateral pool (representing his max possible loss). Later, Bob exits his position by selling at a price of 95. The amount of Token A now allocated to Bob's account is 45 (35 of which is his original collateral and 10 of which represents his profit from his trade) and is now able to be withdrawn from the smart contract if Bob so wishes.

    Can a contract be created based on a different blockchain or off chain asset?

    Yes, by using oracle solutions for settlement users can create contracts for any type of real world asset such as the SP500, or cross chain asset prices like Bitcoin or Monero. This opens endless opportunities and diversification for the holders of ERC20 tokens who do not want to convert into fiat but want to gain market exposure to non digital or cross chain assets.

    Do you have a white paper available?

    Yes! Please select a language below

    How will disputes be resolved?

    This is an area of active research and discussion. We would love for community feedback to help shape the process. Our current working theory is that once a contract settlement enters into a disputed state, that a second attempt may be made to use the originally agreed upon oracle, and if that still fails to enter into a crowd sourced voting from community members that are incentivized for a fair resolution. We do anticipate that even in the best of circumstances oracle solutions will fail, or receive bad data. The problem of bad or inaccurate market data is not new or unique in the world of finance, but the need to resolve these problems when they arise in a trust-less manner will be essential.

    How do I get involved?

    We are actively looking to expand our team. For more info please send an email to info@marketprotocol.io

    FAQ - Solidity Smart Contracts

    How to debug MARKET Protocol tests?

    First option is to use console.log() to display Javascript objects and their properties on the console during test execution. This works well for simple cases, for more difficult scenarios one should set an asynchronous event watcher and expect events sent from Solidity contracts. For tests that have expectation on price or asynchronously wait for contract settlement it is also possible to manually update price using TestableMarketContractOraclize contract to verify correctness of the contract flow.

    FAQ - API

    FAQ - dApp

    Getting help

    Discord

    We work in public and our company Discord is open to all. If you have questions or need help getting started, our Discord #engineering channel is a great place to get assistance from our team of engineers and developers.

    Email

    You can also reach us by email at support@marketprotocol.io.

    Contributing

    Want to hack on MARKET Protocol? Awesome!

    MARKET Protocol is an Open Source project and we welcome contributions of all sorts. There are many ways to help, from reporting issues, contributing code, and helping us improve our community.

    Please, start reading about our:

    Dive Right In

    If you're ready to start helping us to build the decentralized future right now and you just need an issue to focus on, check out this list of open issues.

    There are three main repositories that are considered as core components of the MARKET Protocol:

    Note that the README file of each one of these repositories has a helpful Getting Started section. Plus, you will find a CONTRIBUTING.md file with additional details in all of them as well.

    Remember to join our Discord Community to get in touch with our dev staff and other contributors. We will love to see you there.

    We appreciate your contribution and we hope you have lots of fun while working on MARKET Protocol!

    Development Process

    We follow the GitFlow branching model for development. The latest merged code generally lives in the develop branch of each repository. Your development flow should look like:

    1. Find an interesting issue and communicate! Please let the #engineering Discord channel know what you want to work on
    2. Add a comment to the issue so we don't have multiple contributors unintentionally working on the same task.
    3. Please include your intended solution and a time frame for completion in the issue.
    4. Start with the develop branch and create a new feature branch
    5. Follow the appropriate coding style and write some awesome code
    6. See here for some notes on good commit messages
    7. Open a pull request to the develop branch, not master

    Gitcoin and Bounties

    We are very proud users of Gitcoin. It allows us an easy way to reward our community members for their hard work contributing to MARKET Protocol. Additionally, it allows us to gain traction on issues that are a priority for us to address. We won't always stake every issue, but if you need a bounty to encourage your participation on an issue, and there isn't one yet, please reach out on Discord.

    There are a few guidelines when using Gitcoin that are worth mentioning

    1. Please only start work on an issue when your actually planning on working on it. Don't call dibs before you can allocate time to the issue
    2. Please make sure to comment in the issue immediately after starting work so we know your plans for implementation and a timeline.
    3. We politely ask that users only have open work on a single bounty at a time, if you have an open bounty that has a PR submitted and would like to tackle another issue, please ask in Discord before proceeding
    4. We will do our best to scope out the issue, but please anticipate some revision requested after you have submitted a PR, we are happy to tip you if these end up well beyond the initial scope
    5. Once you have create a PR, please submit work on Gitcoin so we are able to pay you out once we have accepted the work

    Coding Style

    We use a variety of programming languages in our repositories. When contributing, please follow the existing coding conventions according to the CONTRIBUTING.md file of each repository.

    Project Link
    website website
    dApp dApp
    MARKETProtocol MARKETProtocol
    MARKET.js MARKET.js

    Git Flow

    We are implementing Git Flow for our branching model.

    Git Branching

    Branching

    $ git checkout -b feature/my-feature develop
    and hotfix branches (prefixed with hotfix/ by convention) off of master:
    
    # hotfix the latest version of master
    $ git checkout -b hotfix/hotfix-version-number master
    
    # or hotfix from a specific version
    $ git checkout -b hotfix/hotfix-version-number <starting-tag-name>
    

    The main trunks which are persistent are develop and master; Master holds the latest release and develop holds the latest stable development copy.

    Contributors create feature branches (prefixed with feature/ by convention) off of develop.

    These new branches are disposable, meaning they have a short lifespan before they are merged back to the main trunks. They are meant to encapsulate small pieces of functionality.

    Finishing Branches

     $ git checkout develop
     $ git merge --no-ff feature/my-feature
     $ git branch -d feature/my-feature
    

    When a contributor is done with a feature branch, they merge it back into develop, or create a pull request in order to have MARKET Protocol core team do so.

    For a hotfix branch, it is merged back into both master and develop so the hotfix carries forward

     $ git checkout master
     $ git merge --no-ff hotfix/hotfix-version-number
     $ git checkout develop
     $ git merge --no-ff hotfix/hotfix-version-number
     $ git branch -d hotfix/hotfix-version-number
    

    Releases

    A release branch is created from the stable develop branch with a tag.

    Using a separate release branch allows us to continue developing new features on develop while we fix bugs and add finishing touches to a release branch.

    When we are ready to finish the release, we merge the release branch into both master and develop (just like a hotfix) so that all changes carry forward. The master branch is tagged at this point as well to mark the released code.

    Merging

    $ git merge --no-ff <branch-name>
    

    Git flow encourages merging of branches with --no-ff

    The --no-ff option allows you to maintain all of your branch history without leaving a bunch of branches lying around in the current commit of the repository.

    $ git pull --rebase
    

    Similarly, best practice is to pull with --rebase to avoid lots of useless merge commits.

    You can configure git to do both of these things by default in your .gitconfig

    git-flow extension

    Using the git-flow extension can greatly simplify your life and is recommended

    Community Guidelines

    We want to keep the MARKET Protocol community awesome, growing and collaborative. We need your help to keep it that way. To help with this we've come up with some general guidelines for the community as a whole:

    Full code of conduct is posted available here.

    Engineering Weekly

    Once a week, we all get together to talk about the project.

    In the Engineering Weekly meeting, the core engineering team and contributors check in to discuss the progress of the project, to call attention to particular items, to make announcements, or to seek discussion of a topic.

    Everyone is welcome! Check details here.

    And you can find the notes from previous meetings here.

    Community Improvement

    MARKET Protocol is just as much about community as it is about our technology.

    We need constant help in improving our documentation, building new tools to interface with our platform, spreading the word to new users, helping new users getting setup and much more.

    Please get in touch if you would like to help out. Our general channel on Discord is a great place to share ideas and volunteer to help.

    Full Time Positions

    MARKET Protocol occasionally hires developers for part time or full time positions.

    We have a strong preference for hiring people who have already started contributing to the project. If you want a full time position on our team, your best shot is to engage with our team and start contributing code. It is very unlikely that we would offer you a full time position on our engineering team unless you've had at least a few pull requests merged.

    Bug Reporting

    If you find bugs, mistakes or inconsistencies, please let us know by filing an issue on GitHub (see details bellow). We highly appreciate you taking the time to contributing to MARKET Protocol.

    We use GitHub for many aspects of project management, including recording meeting notes, outstanding decisions, documenting requests, and filing bugs. Therefore, if you ever find a bug in any of our applications, please report it on GitHub. See details below.

    What's GitHub?

    GitHub is a version control system, a place where developers store their code. It's the place where our community stores all the code for our entire project.

    GitHub allows groups of developers to collaborate on the same documents (often source code) simultaneously and without overriding each other’s work.

    Create a GitHub account

    In order to report your findings on GitHub, you need to have a GitHub account. If you don't have one yet, you can easily sign up for one for free.

    Please, see: Signing up for a new GitHub account

    Creating a Bug Report

    To report a bug related to MARKET Protocol applications, please create an issue in our GitHub.

    In our GitHub repositories, issues can be created by anyone and are then moderated by our core collaborators.

    To create a new issue in our GitHub click on this link, or you view existing issues and click on the New Issue button to add yours.

    If you are able, please help us by creating the issue in the correct sub project, using the links below.

    When filing a new bug, please include:

    See also: Creating an issue

    Security Issues

    The MARKET Protocol and its implementations are still in early development, which means there may be problems with the protocol or in our implementations. We take security vulnerabilities very seriously. If you discover a security issue, please bring it to our attention right away!

    If you find a vulnerability please send your report privately to support@marketprotocol.io Please DO NOT file a public issue.

    If the issue is a protocol weakness or something not yet deployed, feel free to discuss it openly.