Create a market

To create a market, the user calls one of the market creation functions inside the MarketFactory contract. The steps to create a prediction market are quite similar among different market types.

For example, the following function may be used to create a categorical market:

function createCategoricalMarket(CreateMarketParams calldata params) external returns (address)

Parameter: the function call requires a CreateMarketParams struct

struct CreateMarketParams {
    string marketName; // Used only in categorical, multi categorical, and scalar markets. In multi scalar markets, the market name is formed using questionStart + outcomeType + questionEnd.
    string[] outcomes; // The market outcomes, doesn't include the INVALID_RESULT outcome
    string questionStart; // Used to build the Reality question on multi scalar markets
    string questionEnd; // Used to build the Reality question on multi scalar markets
    string outcomeType; // Used to build the Reality question on multi scalar markets
    uint256 parentOutcome; // conditional outcome to use (optional)
    address parentMarket; // conditional market to use (optional)
    string category; // Reality question category
    string lang; // Reality question language
    uint256 lowerBound; // Lower bound, only used for scalar markets
    uint256 upperBound; // Upper bound, only user for scalar markets
    uint256 minBond; // Min bond to use on Reality
    uint32 openingTime; // Reality question opening time
    string[] tokenNames; // Name of the ERC20 tokens associated to each outcome
}

If the function succeeds, the newly created market address will be stored in a state variable:

address[] public markets; // Markets created by this factory

while the actual market information will be stored in a separate Market contract:

Market.sol
struct RealityParams {
    bytes32[] questionsIds; // Reality questions ids
    uint256 templateId; // Reality templateId
    string[] encodedQuestions; // Encoded questions parameters, needed to create and reopen a question
}

struct ConditionalTokensParams {
    bytes32 conditionId; // Conditional Tokens conditionId
    bytes32 parentCollectionId; // Conditional Tokens parentCollectionId
    uint256 parentOutcome; // conditional outcome to use (optional)
    address parentMarket; // conditional market to use (optional)
    bytes32 questionId; // Conditional Tokens questionId
    IERC20[] wrapped1155; //ERC20 tokens addresses
    bytes[] data; //ERC20 tokens data
}

string public marketName; // The name of the market
string[] public outcomes; // The market outcomes, doesn't include the INVALID_RESULT outcome
uint256 public lowerBound; // Lower bound, only used for scalar markets
uint256 public upperBound; // Upper bound, only user for scalar markets
ConditionalTokensParams public conditionalTokensParams; // Conditional Tokens parameters
RealityParams public realityParams; // Reality parameters
questionId is a hash of all the values that RealityProxy.resolve() uses to resolve a market, this way if an attacker tries to resolve a fake market by changing some value its questionId will not match the id of a valid market

bytes32 questionId = keccak256(
    abi.encode(
        questionsIds,
        params.outcomes.length,
        config.templateId,
        params.lowerBound,
        params.upperBound
    )
);

For multi-scalar markets, marketName is questionStart + outcomeType + questionEnd

and an event will be emitted:

event NewMarket(
    address indexed market,
    string marketName,
    address parentMarket,
    bytes32 conditionId,
    bytes32 questionId,
    bytes32[] questionsIds
);

When creating a market, the contract will also:

  1. Setup one or multiple Reality questions. A market may contain one or multiple questions waiting to be resolved by an oracle. Reality is chosen for this task.

function askRealityQuestion(
   string memory encodedQuestion,
   uint256 templateId,
   uint32 openingTime,
   uint256 minBond
) internal returns (bytes32)
  1. Prepare a Condition. Each market corresponds to a conditionId. This conditionId will be used in the ConditionalTokens contract to resolve the market.

function prepareCondition(
    bytes32 questionId,
    uint outcomeSlotCount
) internal returns (bytes32)
  1. ERC20 Position Tokens Creation. For each possible outcome (including an "Invalid" outcome), the contract creates a wrapped ERC20 token representing this position using Wrapped1155Factory. The tokens addresses and data will be saved in the Market contract.

function deployERC20Positions(
    bytes32 parentCollectionId,
    bytes32 conditionId,
    uint256 outcomeSlotCount,
    string[] memory tokenNames
) internal returns (IERC20[] memory wrapped1155, bytes[] memory data)

Last updated