Contract 0x8b9805a2f595b6705e74f7310829f2d299d21522

 

Contract Overview

Balance:
0 MATIC

MATIC Value:
$0.00

Token:
 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xccb81d35d68c3de7e3fe49d0d61733a758d37328d1d2feda85328c65a45f131cTransfer*359820802022-11-23 21:31:532 days 15 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.014761568 32
0x325d22290dd41d35fe628526d9fe3a3f05d0273c54daea2b18d25e58fd8c86b3Transfer*359385382022-11-22 20:02:133 days 16 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.025877243 49
0x22456702c4116fc92cadd6a038d439fec8a724d05a6d098f64cca78413d04083Transfer*359381802022-11-22 19:49:573 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.023096205 45
0x318c24650862449d431e3a20a72c6cb98b3119790dca8c6897e1ba113b6fe3a6Transfer*359380542022-11-22 19:43:313 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.02377495 47
0xf8009d9ee5417dabae04cfb61eb6b679d2177d867823ec527fb4bf12dcf97e08Transfer*359378902022-11-22 19:36:563 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.030401424 61
0x76ec98aff6c1e0800197f3877142d69d7b1977374cec9d7b0693ffd08634b52eTransfer*359377422022-11-22 19:31:523 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.030946944 64
0xbad0c33c2185fd2f403b48d14457b211fbc25bea91493713772170f9a958076bTransfer*359025372022-11-21 23:05:244 days 13 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.02013141 41
0x311cb6d17685dd6648801ff6ac4daff3c55ef12271922fec09ef0d4a9358f8ebTransfer*359016752022-11-21 22:35:394 days 14 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.024659826 51
0x2045531641f055864b72350ebff941c331a1a4a4417ffebdb7919eea4992c05bTransfer*359005172022-11-21 21:55:394 days 15 hrs ago0x91430cad2d3975766499717fa0d66a78d814e5c5 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.023920896 48
0xeaf44f97e3796371fa9d8a3ebd0c0a7b6199427b873ef7ed0b8a042dd4fdfc09Transfer*358975362022-11-21 20:13:104 days 16 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.029982485 65
0xb151a811b82adf5c746e7114049b53505e07abbe25a2b53d27e3bd6768152ae9Transfer*358974282022-11-21 20:09:264 days 16 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.038432416 82
0xdf3937611d4586e20d49fe53f682bbe37a67b4be3b185f09b8f161c5cd6c07eeTransfer*358972802022-11-21 20:04:204 days 16 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.02343665 50
0x95b33f93c215b6c9d2288f59511d43663e09e91519017b77393d27289a7b43ceTransfer*358970212022-11-21 19:55:224 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.022498464 48
0xbc134958bb42278ee8b19e884f9a9a9554c76a7f6ad7cc0aa2b2b1240d554ef2Transfer*358969142022-11-21 19:51:434 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.03191578 65
0x0374e0a83bc07b9ce238f8cc90f0310f56608e1956e04e9ed8d6f5b2b66a5612Transfer*358967162022-11-21 19:44:554 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.059992064 128
0x1d3bd2542beb09f3afb8601f8f2dbf093d7000782f0ee23bdf511f96504fb9a7Transfer*358965792022-11-21 19:40:134 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.337515108 698
0x8c47634223ae9474a58b59d1d5670bc92fb3524fd891a973d473ebb3f1869368Transfer*358965072022-11-21 19:37:414 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.178071498 374
0x06dcb2797c1c6822eae7bd746cd87119a932c9535b5d0febd5a733f479a986eeTransfer*358963042022-11-21 19:30:434 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.103339264 224
0x739cb0da718526c6632cf4b0281fc5b171fc11582c79740c9bf3bf83b8002ffcTransfer*358961862022-11-21 19:26:394 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.0245491 50
0x184f8855277b25b99f47bd0480fe663c8c914d2c6b45b794c772c31eb4e0a2c4Transfer*358961052022-11-21 19:23:534 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.015468915 33
0x94ce90937ce0d7ed0bb13cc0c177b63b8019d654d969e3ecbdf813af05df9069Transfer*358959572022-11-21 19:18:494 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.015221316 33
0x3481fa4a2c91d46634b9d3e55acf42b81cda3efa1cbcb8adf349e2e534a698caTransfer*358958582022-11-21 19:15:234 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.019374852 42
0x9d7ca3cdc4798f84eae469256a289868ef557f05c4ecf3bd71f5130fb753e7efTransfer*358957192022-11-21 19:10:374 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.029064798 63
0x5aaad4deda6733f266201b203201c84e629e8f07cc43af5510f0338c76a5a5b6Transfer*358956492022-11-21 19:07:134 days 17 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.02531277 54
0x230aa8e50c149aab52ca1ad98d1717c14a44695bec76190fd4effd6c36fd6f3eTransfer*358954422022-11-21 18:58:594 days 18 hrs ago0x281777d3bdd096d302791f94a2e429bb98474227 IN 0x8b9805a2f595b6705e74f7310829f2d299d215220 MATIC0.02156319 46
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xccb81d35d68c3de7e3fe49d0d61733a758d37328d1d2feda85328c65a45f131c359820802022-11-23 21:31:532 days 15 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x325d22290dd41d35fe628526d9fe3a3f05d0273c54daea2b18d25e58fd8c86b3359385382022-11-22 20:02:133 days 16 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x22456702c4116fc92cadd6a038d439fec8a724d05a6d098f64cca78413d04083359381802022-11-22 19:49:573 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x318c24650862449d431e3a20a72c6cb98b3119790dca8c6897e1ba113b6fe3a6359380542022-11-22 19:43:313 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0xf8009d9ee5417dabae04cfb61eb6b679d2177d867823ec527fb4bf12dcf97e08359378902022-11-22 19:36:563 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x76ec98aff6c1e0800197f3877142d69d7b1977374cec9d7b0693ffd08634b52e359377422022-11-22 19:31:523 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0xbad0c33c2185fd2f403b48d14457b211fbc25bea91493713772170f9a958076b359025372022-11-21 23:05:244 days 13 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x311cb6d17685dd6648801ff6ac4daff3c55ef12271922fec09ef0d4a9358f8eb359016752022-11-21 22:35:394 days 14 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x2045531641f055864b72350ebff941c331a1a4a4417ffebdb7919eea4992c05b359005172022-11-21 21:55:394 days 15 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0xeaf44f97e3796371fa9d8a3ebd0c0a7b6199427b873ef7ed0b8a042dd4fdfc09358975362022-11-21 20:13:104 days 16 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0xb151a811b82adf5c746e7114049b53505e07abbe25a2b53d27e3bd6768152ae9358974282022-11-21 20:09:264 days 16 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0xdf3937611d4586e20d49fe53f682bbe37a67b4be3b185f09b8f161c5cd6c07ee358972802022-11-21 20:04:204 days 16 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x95b33f93c215b6c9d2288f59511d43663e09e91519017b77393d27289a7b43ce358970212022-11-21 19:55:224 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0xbc134958bb42278ee8b19e884f9a9a9554c76a7f6ad7cc0aa2b2b1240d554ef2358969142022-11-21 19:51:434 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x0374e0a83bc07b9ce238f8cc90f0310f56608e1956e04e9ed8d6f5b2b66a5612358967162022-11-21 19:44:554 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x1d3bd2542beb09f3afb8601f8f2dbf093d7000782f0ee23bdf511f96504fb9a7358965792022-11-21 19:40:134 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x8c47634223ae9474a58b59d1d5670bc92fb3524fd891a973d473ebb3f1869368358965072022-11-21 19:37:414 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x06dcb2797c1c6822eae7bd746cd87119a932c9535b5d0febd5a733f479a986ee358963042022-11-21 19:30:434 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x739cb0da718526c6632cf4b0281fc5b171fc11582c79740c9bf3bf83b8002ffc358961862022-11-21 19:26:394 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x184f8855277b25b99f47bd0480fe663c8c914d2c6b45b794c772c31eb4e0a2c4358961052022-11-21 19:23:534 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x94ce90937ce0d7ed0bb13cc0c177b63b8019d654d969e3ecbdf813af05df9069358959572022-11-21 19:18:494 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x3481fa4a2c91d46634b9d3e55acf42b81cda3efa1cbcb8adf349e2e534a698ca358958582022-11-21 19:15:234 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x9d7ca3cdc4798f84eae469256a289868ef557f05c4ecf3bd71f5130fb753e7ef358957192022-11-21 19:10:374 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x5aaad4deda6733f266201b203201c84e629e8f07cc43af5510f0338c76a5a5b6358956492022-11-21 19:07:134 days 17 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
0x230aa8e50c149aab52ca1ad98d1717c14a44695bec76190fd4effd6c36fd6f3e358954422022-11-21 18:58:594 days 18 hrs ago 0x8b9805a2f595b6705e74f7310829f2d299d21522  Contract Creation0 MATIC
[ Download CSV Export 
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
FixedProductMarketMakerFactory

Compiler Version
v0.5.10+commit.5a6ea5b1

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU LGPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at polygonscan.com on 2022-10-31
*/

// Sources flattened with hardhat v2.12.1 https://hardhat.org

// File openzeppelin-solidity/contracts/math/[email protected]

pragma solidity ^0.5.0;

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

        return c;
    }

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

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     *
     * _Available since v2.4.0._
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

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

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

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

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

        return c;
    }

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

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


// File openzeppelin-solidity/contracts/token/ERC20/[email protected]

pragma solidity ^0.5.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see {ERC20Detailed}.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: 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
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}


// File contracts/ERC20.sol

// This is a backported hooked OpenZeppelin ERC 20 implementation
pragma solidity ^0.5.0;


/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20Mintable}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public returns (bool) {
        _approve(msg.sender, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20};
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for `sender`'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount);
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        _balances[account] = _balances[account].sub(amount);
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`.`amount` is then deducted
     * from the caller's allowance.
     *
     * See {_burn} and {_approve}.
     */
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount));
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of `from`'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of `from`'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:using-hooks.adoc[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal { }
}


// File @gnosis.pm/conditional-tokens-contracts/contracts/[email protected]

pragma solidity ^0.5.1;

library CTHelpers {
    /// @dev Constructs a condition ID from an oracle, a question ID, and the outcome slot count for the question.
    /// @param oracle The account assigned to report the result for the prepared condition.
    /// @param questionId An identifier for the question to be answered by the oracle.
    /// @param outcomeSlotCount The number of outcome slots which should be used for this condition. Must not exceed 256.
    function getConditionId(address oracle, bytes32 questionId, uint outcomeSlotCount) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(oracle, questionId, outcomeSlotCount));
    }

    uint constant P = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
    uint constant B = 3;

    function sqrt(uint x) private pure returns (uint y) {
        uint p = P;
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            // add chain generated via https://crypto.stackexchange.com/q/27179/71252
            // and transformed to the following program:

            // x=1; y=x+x; z=y+y; z=z+z; y=y+z; x=x+y; y=y+x; z=y+y; t=z+z; t=z+t; t=t+t;
            // t=t+t; z=z+t; x=x+z; z=x+x; z=z+z; y=y+z; z=y+y; z=z+z; z=z+z; z=y+z; x=x+z;
            // z=x+x; z=z+z; z=z+z; z=x+z; y=y+z; x=x+y; z=x+x; z=z+z; y=y+z; z=y+y; t=z+z;
            // t=t+t; t=t+t; z=z+t; x=x+z; y=y+x; z=y+y; z=z+z; z=z+z; x=x+z; z=x+x; z=z+z;
            // z=x+z; z=z+z; z=z+z; z=x+z; y=y+z; z=y+y; t=z+z; t=t+t; t=z+t; t=y+t; t=t+t;
            // t=t+t; t=t+t; t=t+t; z=z+t; x=x+z; z=x+x; z=x+z; y=y+z; z=y+y; z=y+z; z=z+z;
            // t=z+z; t=z+t; w=t+t; w=w+w; w=w+w; w=w+w; w=w+w; t=t+w; z=z+t; x=x+z; y=y+x;
            // z=y+y; x=x+z; y=y+x; x=x+y; y=y+x; x=x+y; z=x+x; z=x+z; z=z+z; y=y+z; z=y+y;
            // z=z+z; x=x+z; y=y+x; z=y+y; z=y+z; x=x+z; y=y+x; x=x+y; y=y+x; z=y+y; z=z+z;
            // z=y+z; x=x+z; z=x+x; z=x+z; y=y+z; x=x+y; y=y+x; x=x+y; y=y+x; z=y+y; z=y+z;
            // z=z+z; x=x+z; y=y+x; z=y+y; z=y+z; z=z+z; x=x+z; z=x+x; t=z+z; t=t+t; t=z+t;
            // t=x+t; t=t+t; t=t+t; t=t+t; t=t+t; z=z+t; y=y+z; x=x+y; y=y+x; x=x+y; z=x+x;
            // z=x+z; z=z+z; z=z+z; z=z+z; z=x+z; y=y+z; z=y+y; z=y+z; z=z+z; x=x+z; z=x+x;
            // z=x+z; y=y+z; x=x+y; z=x+x; z=z+z; y=y+z; x=x+y; z=x+x; y=y+z; x=x+y; y=y+x;
            // z=y+y; z=y+z; x=x+z; y=y+x; z=y+y; z=y+z; z=z+z; z=z+z; x=x+z; z=x+x; z=z+z;
            // z=z+z; z=x+z; y=y+z; x=x+y; z=x+x; t=x+z; t=t+t; t=t+t; z=z+t; y=y+z; z=y+y;
            // x=x+z; y=y+x; x=x+y; y=y+x; x=x+y; y=y+x; z=y+y; t=y+z; z=y+t; z=z+z; z=z+z;
            // z=t+z; x=x+z; y=y+x; x=x+y; y=y+x; x=x+y; z=x+x; z=x+z; y=y+z; x=x+y; x=x+x;
            // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x;
            // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x;
            // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x;
            // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x;
            // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x;
            // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x;
            // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x;
            // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x;
            // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x;
            // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x;
            // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x;
            // x=x+x; x=x+x; x=x+x; x=x+x; res=y+x
            // res == (P + 1) // 4

            y := mulmod(x, x, p)
            {
                let z := mulmod(y, y, p)
                z := mulmod(z, z, p)
                y := mulmod(y, z, p)
                x := mulmod(x, y, p)
                y := mulmod(y, x, p)
                z := mulmod(y, y, p)
                {
                    let t := mulmod(z, z, p)
                    t := mulmod(z, t, p)
                    t := mulmod(t, t, p)
                    t := mulmod(t, t, p)
                    z := mulmod(z, t, p)
                    x := mulmod(x, z, p)
                    z := mulmod(x, x, p)
                    z := mulmod(z, z, p)
                    y := mulmod(y, z, p)
                    z := mulmod(y, y, p)
                    z := mulmod(z, z, p)
                    z := mulmod(z, z, p)
                    z := mulmod(y, z, p)
                    x := mulmod(x, z, p)
                    z := mulmod(x, x, p)
                    z := mulmod(z, z, p)
                    z := mulmod(z, z, p)
                    z := mulmod(x, z, p)
                    y := mulmod(y, z, p)
                    x := mulmod(x, y, p)
                    z := mulmod(x, x, p)
                    z := mulmod(z, z, p)
                    y := mulmod(y, z, p)
                    z := mulmod(y, y, p)
                    t := mulmod(z, z, p)
                    t := mulmod(t, t, p)
                    t := mulmod(t, t, p)
                    z := mulmod(z, t, p)
                    x := mulmod(x, z, p)
                    y := mulmod(y, x, p)
                    z := mulmod(y, y, p)
                    z := mulmod(z, z, p)
                    z := mulmod(z, z, p)
                    x := mulmod(x, z, p)
                    z := mulmod(x, x, p)
                    z := mulmod(z, z, p)
                    z := mulmod(x, z, p)
                    z := mulmod(z, z, p)
                    z := mulmod(z, z, p)
                    z := mulmod(x, z, p)
                    y := mulmod(y, z, p)
                    z := mulmod(y, y, p)
                    t := mulmod(z, z, p)
                    t := mulmod(t, t, p)
                    t := mulmod(z, t, p)
                    t := mulmod(y, t, p)
                    t := mulmod(t, t, p)
                    t := mulmod(t, t, p)
                    t := mulmod(t, t, p)
                    t := mulmod(t, t, p)
                    z := mulmod(z, t, p)
                    x := mulmod(x, z, p)
                    z := mulmod(x, x, p)
                    z := mulmod(x, z, p)
                    y := mulmod(y, z, p)
                    z := mulmod(y, y, p)
                    z := mulmod(y, z, p)
                    z := mulmod(z, z, p)
                    t := mulmod(z, z, p)
                    t := mulmod(z, t, p)
                    {
                        let w := mulmod(t, t, p)
                        w := mulmod(w, w, p)
                        w := mulmod(w, w, p)
                        w := mulmod(w, w, p)
                        w := mulmod(w, w, p)
                        t := mulmod(t, w, p)
                    }
                    z := mulmod(z, t, p)
                    x := mulmod(x, z, p)
                    y := mulmod(y, x, p)
                    z := mulmod(y, y, p)
                    x := mulmod(x, z, p)
                    y := mulmod(y, x, p)
                    x := mulmod(x, y, p)
                    y := mulmod(y, x, p)
                    x := mulmod(x, y, p)
                    z := mulmod(x, x, p)
                    z := mulmod(x, z, p)
                    z := mulmod(z, z, p)
                    y := mulmod(y, z, p)
                    z := mulmod(y, y, p)
                    z := mulmod(z, z, p)
                    x := mulmod(x, z, p)
                    y := mulmod(y, x, p)
                    z := mulmod(y, y, p)
                    z := mulmod(y, z, p)
                    x := mulmod(x, z, p)
                    y := mulmod(y, x, p)
                    x := mulmod(x, y, p)
                    y := mulmod(y, x, p)
                    z := mulmod(y, y, p)
                    z := mulmod(z, z, p)
                    z := mulmod(y, z, p)
                    x := mulmod(x, z, p)
                    z := mulmod(x, x, p)
                    z := mulmod(x, z, p)
                    y := mulmod(y, z, p)
                    x := mulmod(x, y, p)
                    y := mulmod(y, x, p)
                    x := mulmod(x, y, p)
                    y := mulmod(y, x, p)
                    z := mulmod(y, y, p)
                    z := mulmod(y, z, p)
                    z := mulmod(z, z, p)
                    x := mulmod(x, z, p)
                    y := mulmod(y, x, p)
                    z := mulmod(y, y, p)
                    z := mulmod(y, z, p)
                    z := mulmod(z, z, p)
                    x := mulmod(x, z, p)
                    z := mulmod(x, x, p)
                    t := mulmod(z, z, p)
                    t := mulmod(t, t, p)
                    t := mulmod(z, t, p)
                    t := mulmod(x, t, p)
                    t := mulmod(t, t, p)
                    t := mulmod(t, t, p)
                    t := mulmod(t, t, p)
                    t := mulmod(t, t, p)
                    z := mulmod(z, t, p)
                    y := mulmod(y, z, p)
                    x := mulmod(x, y, p)
                    y := mulmod(y, x, p)
                    x := mulmod(x, y, p)
                    z := mulmod(x, x, p)
                    z := mulmod(x, z, p)
                    z := mulmod(z, z, p)
                    z := mulmod(z, z, p)
                    z := mulmod(z, z, p)
                    z := mulmod(x, z, p)
                    y := mulmod(y, z, p)
                    z := mulmod(y, y, p)
                    z := mulmod(y, z, p)
                    z := mulmod(z, z, p)
                    x := mulmod(x, z, p)
                    z := mulmod(x, x, p)
                    z := mulmod(x, z, p)
                    y := mulmod(y, z, p)
                    x := mulmod(x, y, p)
                    z := mulmod(x, x, p)
                    z := mulmod(z, z, p)
                    y := mulmod(y, z, p)
                    x := mulmod(x, y, p)
                    z := mulmod(x, x, p)
                    y := mulmod(y, z, p)
                    x := mulmod(x, y, p)
                    y := mulmod(y, x, p)
                    z := mulmod(y, y, p)
                    z := mulmod(y, z, p)
                    x := mulmod(x, z, p)
                    y := mulmod(y, x, p)
                    z := mulmod(y, y, p)
                    z := mulmod(y, z, p)
                    z := mulmod(z, z, p)
                    z := mulmod(z, z, p)
                    x := mulmod(x, z, p)
                    z := mulmod(x, x, p)
                    z := mulmod(z, z, p)
                    z := mulmod(z, z, p)
                    z := mulmod(x, z, p)
                    y := mulmod(y, z, p)
                    x := mulmod(x, y, p)
                    z := mulmod(x, x, p)
                    t := mulmod(x, z, p)
                    t := mulmod(t, t, p)
                    t := mulmod(t, t, p)
                    z := mulmod(z, t, p)
                    y := mulmod(y, z, p)
                    z := mulmod(y, y, p)
                    x := mulmod(x, z, p)
                    y := mulmod(y, x, p)
                    x := mulmod(x, y, p)
                    y := mulmod(y, x, p)
                    x := mulmod(x, y, p)
                    y := mulmod(y, x, p)
                    z := mulmod(y, y, p)
                    t := mulmod(y, z, p)
                    z := mulmod(y, t, p)
                    z := mulmod(z, z, p)
                    z := mulmod(z, z, p)
                    z := mulmod(t, z, p)
                }
                x := mulmod(x, z, p)
                y := mulmod(y, x, p)
                x := mulmod(x, y, p)
                y := mulmod(y, x, p)
                x := mulmod(x, y, p)
                z := mulmod(x, x, p)
                z := mulmod(x, z, p)
                y := mulmod(y, z, p)
            }
            x := mulmod(x, y, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            x := mulmod(x, x, p)
            y := mulmod(y, x, p)
        }
    }

    /// @dev Constructs an outcome collection ID from a parent collection and an outcome collection.
    /// @param parentCollectionId Collection ID of the parent outcome collection, or bytes32(0) if there's no parent.
    /// @param conditionId Condition ID of the outcome collection to combine with the parent outcome collection.
    /// @param indexSet Index set of the outcome collection to combine with the parent outcome collection.
    function getCollectionId(bytes32 parentCollectionId, bytes32 conditionId, uint indexSet) internal view returns (bytes32) {
        uint x1 = uint(keccak256(abi.encodePacked(conditionId, indexSet)));
        bool odd = x1 >> 255 != 0;
        uint y1;
        uint yy;
        do {
            x1 = addmod(x1, 1, P);
            yy = addmod(mulmod(x1, mulmod(x1, x1, P), P), B, P);
            y1 = sqrt(yy);
        } while(mulmod(y1, y1, P) != yy);
        if(odd && y1 % 2 == 0 || !odd && y1 % 2 == 1)
            y1 = P - y1;

        uint x2 = uint(parentCollectionId);
        if(x2 != 0) {
            odd = x2 >> 254 != 0;
            x2 = (x2 << 2) >> 2;
            yy = addmod(mulmod(x2, mulmod(x2, x2, P), P), B, P);
            uint y2 = sqrt(yy);
            if(odd && y2 % 2 == 0 || !odd && y2 % 2 == 1)
                y2 = P - y2;
            require(mulmod(y2, y2, P) == yy, "invalid parent collection ID");

            (bool success, bytes memory ret) = address(6).staticcall(abi.encode(x1, y1, x2, y2));
            require(success, "ecadd failed");
            (x1, y1) = abi.decode(ret, (uint, uint));
        }

        if(y1 % 2 == 1)
            x1 ^= 1 << 254;

        return bytes32(x1);
    }

    /// @dev Constructs a position ID from a collateral token and an outcome collection. These IDs are used as the ERC-1155 ID for this contract.
    /// @param collateralToken Collateral token which backs the position.
    /// @param collectionId ID of the outcome collection associated with this position.
    function getPositionId(IERC20 collateralToken, bytes32 collectionId) internal pure returns (uint) {
        return uint(keccak256(abi.encodePacked(collateralToken, collectionId)));
    }
}


// File openzeppelin-solidity/contracts/utils/[email protected]

pragma solidity ^0.5.5;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following 
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }

    /**
     * @dev Converts an `address` into `address payable`. Note that this is
     * simply a type cast: the actual underlying value is not changed.
     *
     * _Available since v2.4.0._
     */
    function toPayable(address account) internal pure returns (address payable) {
        return address(uint160(account));
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     *
     * _Available since v2.4.0._
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-call-value
        (bool success, ) = recipient.call.value(amount)("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }
}


// File openzeppelin-solidity/contracts/introspection/[email protected]

pragma solidity ^0.5.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}


// File openzeppelin-solidity/contracts/introspection/[email protected]

pragma solidity ^0.5.0;

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts may inherit from this and call {_registerInterface} to declare
 * their support of an interface.
 */
contract ERC165 is IERC165 {
    /*
     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
     */
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;

    /**
     * @dev Mapping of interface ids to whether or not it's supported.
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

    constructor () internal {
        // Derived contracts need only register support for their own interfaces,
        // we register support for ERC165 itself here
        _registerInterface(_INTERFACE_ID_ERC165);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     *
     * Time complexity O(1), guaranteed to always use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool) {
        return _supportedInterfaces[interfaceId];
    }

    /**
     * @dev Registers the contract as an implementer of the interface defined by
     * `interfaceId`. Support of the actual ERC165 interface is automatic and
     * registering its interface id is not required.
     *
     * See {IERC165-supportsInterface}.
     *
     * Requirements:
     *
     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
     */
    function _registerInterface(bytes4 interfaceId) internal {
        require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
        _supportedInterfaces[interfaceId] = true;
    }
}


// File @gnosis.pm/conditional-tokens-contracts/contracts/ERC1155/[email protected]

pragma solidity ^0.5.0;

/**
    @title ERC-1155 Multi Token Standard basic interface
    @dev See https://eips.ethereum.org/EIPS/eip-1155
 */
contract IERC1155 is IERC165 {
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    event URI(string value, uint256 indexed id);

    function balanceOf(address owner, uint256 id) public view returns (uint256);

    function balanceOfBatch(address[] memory owners, uint256[] memory ids) public view returns (uint256[] memory);

    function setApprovalForAll(address operator, bool approved) external;

    function isApprovedForAll(address owner, address operator) external view returns (bool);

    function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;

    function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external;
}


// File @gnosis.pm/conditional-tokens-contracts/contracts/ERC1155/[email protected]

pragma solidity ^0.5.0;

/**
    @title ERC-1155 Multi Token Receiver Interface
    @dev See https://eips.ethereum.org/EIPS/eip-1155
*/
contract IERC1155TokenReceiver is IERC165 {

    /**
        @dev Handles the receipt of a single ERC1155 token type. This function is
        called at the end of a `safeTransferFrom` after the balance has been updated.
        To accept the transfer, this must return
        `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
        (i.e. 0xf23a6e61, or its own function selector).
        @param operator The address which initiated the transfer (i.e. msg.sender)
        @param from The address which previously owned the token
        @param id The ID of the token being transferred
        @param value The amount of tokens being transferred
        @param data Additional data with no specified format
        @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
    */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    )
        external
        returns(bytes4);

    /**
        @dev Handles the receipt of a multiple ERC1155 token types. This function
        is called at the end of a `safeBatchTransferFrom` after the balances have
        been updated. To accept the transfer(s), this must return
        `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
        (i.e. 0xbc197c81, or its own function selector).
        @param operator The address which initiated the batch transfer (i.e. msg.sender)
        @param from The address which previously owned the token
        @param ids An array containing ids of each token being transferred (order and length must match values array)
        @param values An array containing amounts of each token being transferred (order and length must match ids array)
        @param data Additional data with no specified format
        @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
    */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    )
        external
        returns(bytes4);
}


// File @gnosis.pm/conditional-tokens-contracts/contracts/ERC1155/[email protected]

pragma solidity ^0.5.0;





/**
 * @title Standard ERC1155 token
 *
 * @dev Implementation of the basic standard multi-token.
 * See https://eips.ethereum.org/EIPS/eip-1155
 * Originally based on code by Enjin: https://github.com/enjin/erc-1155
 */
contract ERC1155 is ERC165, IERC1155
{
    using SafeMath for uint256;
    using Address for address;

    // Mapping from token ID to owner balances
    mapping (uint256 => mapping(address => uint256)) private _balances;

    // Mapping from owner to operator approvals
    mapping (address => mapping(address => bool)) private _operatorApprovals;

    constructor()
        public
    {
        _registerInterface(
            ERC1155(0).safeTransferFrom.selector ^
            ERC1155(0).safeBatchTransferFrom.selector ^
            ERC1155(0).balanceOf.selector ^
            ERC1155(0).balanceOfBatch.selector ^
            ERC1155(0).setApprovalForAll.selector ^
            ERC1155(0).isApprovedForAll.selector
        );
    }

    /**
        @dev Get the specified address' balance for token with specified ID.
        @param owner The address of the token holder
        @param id ID of the token
        @return The owner's balance of the token type requested
     */
    function balanceOf(address owner, uint256 id) public view returns (uint256) {
        require(owner != address(0), "ERC1155: balance query for the zero address");
        return _balances[id][owner];
    }

    /**
        @dev Get the balance of multiple account/token pairs
        @param owners The addresses of the token holders
        @param ids IDs of the tokens
        @return Balances for each owner and token id pair
     */
    function balanceOfBatch(
        address[] memory owners,
        uint256[] memory ids
    )
        public
        view
        returns (uint256[] memory)
    {
        require(owners.length == ids.length, "ERC1155: owners and IDs must have same lengths");

        uint256[] memory batchBalances = new uint256[](owners.length);

        for (uint256 i = 0; i < owners.length; ++i) {
            require(owners[i] != address(0), "ERC1155: some address in batch balance query is zero");
            batchBalances[i] = _balances[ids[i]][owners[i]];
        }

        return batchBalances;
    }

    /**
     * @dev Sets or unsets the approval of a given operator
     * An operator is allowed to transfer all tokens of the sender on their behalf
     * @param operator address to set the approval
     * @param approved representing the status of the approval to be set
     */
    function setApprovalForAll(address operator, bool approved) external {
        _operatorApprovals[msg.sender][operator] = approved;
        emit ApprovalForAll(msg.sender, operator, approved);
    }

    /**
        @notice Queries the approval status of an operator for a given owner.
        @param owner     The owner of the Tokens
        @param operator  Address of authorized operator
        @return           True if the operator is approved, false if not
    */
    function isApprovedForAll(address owner, address operator) external view returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
        @dev Transfers `value` amount of an `id` from the `from` address to the `to` address specified.
        Caller must be approved to manage the tokens being transferred out of the `from` account.
        If `to` is a smart contract, will call `onERC1155Received` on `to` and act appropriately.
        @param from Source address
        @param to Target address
        @param id ID of the token type
        @param value Transfer amount
        @param data Data forwarded to `onERC1155Received` if `to` is a contract receiver
    */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 value,
        bytes calldata data
    )
        external
    {
        require(to != address(0), "ERC1155: target address must be non-zero");
        require(
            from == msg.sender || _operatorApprovals[from][msg.sender] == true,
            "ERC1155: need operator approval for 3rd party transfers."
        );

        _balances[id][from] = _balances[id][from].sub(value);
        _balances[id][to] = value.add(_balances[id][to]);

        emit TransferSingle(msg.sender, from, to, id, value);

        _doSafeTransferAcceptanceCheck(msg.sender, from, to, id, value, data);
    }

    /**
        @dev Transfers `values` amount(s) of `ids` from the `from` address to the
        `to` address specified. Caller must be approved to manage the tokens being
        transferred out of the `from` account. If `to` is a smart contract, will
        call `onERC1155BatchReceived` on `to` and act appropriately.
        @param from Source address
        @param to Target address
        @param ids IDs of each token type
        @param values Transfer amounts per token type
        @param data Data forwarded to `onERC1155Received` if `to` is a contract receiver
    */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    )
        external
    {
        require(ids.length == values.length, "ERC1155: IDs and values must have same lengths");
        require(to != address(0), "ERC1155: target address must be non-zero");
        require(
            from == msg.sender || _operatorApprovals[from][msg.sender] == true,
            "ERC1155: need operator approval for 3rd party transfers."
        );

        for (uint256 i = 0; i < ids.length; ++i) {
            uint256 id = ids[i];
            uint256 value = values[i];

            _balances[id][from] = _balances[id][from].sub(value);
            _balances[id][to] = value.add(_balances[id][to]);
        }

        emit TransferBatch(msg.sender, from, to, ids, values);

        _doSafeBatchTransferAcceptanceCheck(msg.sender, from, to, ids, values, data);
    }

    /**
     * @dev Internal function to mint an amount of a token with the given ID
     * @param to The address that will own the minted token
     * @param id ID of the token to be minted
     * @param value Amount of the token to be minted
     * @param data Data forwarded to `onERC1155Received` if `to` is a contract receiver
     */
    function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {
        require(to != address(0), "ERC1155: mint to the zero address");

        _balances[id][to] = value.add(_balances[id][to]);
        emit TransferSingle(msg.sender, address(0), to, id, value);

        _doSafeTransferAcceptanceCheck(msg.sender, address(0), to, id, value, data);
    }

    /**
     * @dev Internal function to batch mint amounts of tokens with the given IDs
     * @param to The address that will own the minted token
     * @param ids IDs of the tokens to be minted
     * @param values Amounts of the tokens to be minted
     * @param data Data forwarded to `onERC1155Received` if `to` is a contract receiver
     */
    function _batchMint(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal {
        require(to != address(0), "ERC1155: batch mint to the zero address");
        require(ids.length == values.length, "ERC1155: IDs and values must have same lengths");

        for(uint i = 0; i < ids.length; i++) {
            _balances[ids[i]][to] = values[i].add(_balances[ids[i]][to]);
        }

        emit TransferBatch(msg.sender, address(0), to, ids, values);

        _doSafeBatchTransferAcceptanceCheck(msg.sender, address(0), to, ids, values, data);
    }

    /**
     * @dev Internal function to burn an amount of a token with the given ID
     * @param owner Account which owns the token to be burnt
     * @param id ID of the token to be burnt
     * @param value Amount of the token to be burnt
     */
    function _burn(address owner, uint256 id, uint256 value) internal {
        _balances[id][owner] = _balances[id][owner].sub(value);
        emit TransferSingle(msg.sender, owner, address(0), id, value);
    }

    /**
     * @dev Internal function to batch burn an amounts of tokens with the given IDs
     * @param owner Account which owns the token to be burnt
     * @param ids IDs of the tokens to be burnt
     * @param values Amounts of the tokens to be burnt
     */
    function _batchBurn(address owner, uint256[] memory ids, uint256[] memory values) internal {
        require(ids.length == values.length, "ERC1155: IDs and values must have same lengths");

        for(uint i = 0; i < ids.length; i++) {
            _balances[ids[i]][owner] = _balances[ids[i]][owner].sub(values[i]);
        }

        emit TransferBatch(msg.sender, owner, address(0), ids, values);
    }

    function _doSafeTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256 id,
        uint256 value,
        bytes memory data
    )
        internal
    {
        if(to.isContract()) {
            require(
                IERC1155TokenReceiver(to).onERC1155Received(operator, from, id, value, data) ==
                    IERC1155TokenReceiver(to).onERC1155Received.selector,
                "ERC1155: got unknown value from onERC1155Received"
            );
        }
    }

    function _doSafeBatchTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory values,
        bytes memory data
    )
        internal
    {
        if(to.isContract()) {
            require(
                IERC1155TokenReceiver(to).onERC1155BatchReceived(operator, from, ids, values, data) == IERC1155TokenReceiver(to).onERC1155BatchReceived.selector,
                "ERC1155: got unknown value from onERC1155BatchReceived"
            );
        }
    }
}


// File @gnosis.pm/conditional-tokens-contracts/contracts/[email protected]

pragma solidity ^0.5.1;



contract ConditionalTokens is ERC1155 {

    /// @dev Emitted upon the successful preparation of a condition.
    /// @param conditionId The condition's ID. This ID may be derived from the other three parameters via ``keccak256(abi.encodePacked(oracle, questionId, outcomeSlotCount))``.
    /// @param oracle The account assigned to report the result for the prepared condition.
    /// @param questionId An identifier for the question to be answered by the oracle.
    /// @param outcomeSlotCount The number of outcome slots which should be used for this condition. Must not exceed 256.
    event ConditionPreparation(
        bytes32 indexed conditionId,
        address indexed oracle,
        bytes32 indexed questionId,
        uint outcomeSlotCount
    );

    event ConditionResolution(
        bytes32 indexed conditionId,
        address indexed oracle,
        bytes32 indexed questionId,
        uint outcomeSlotCount,
        uint[] payoutNumerators
    );

    /// @dev Emitted when a position is successfully split.
    event PositionSplit(
        address indexed stakeholder,
        IERC20 collateralToken,
        bytes32 indexed parentCollectionId,
        bytes32 indexed conditionId,
        uint[] partition,
        uint amount
    );
    /// @dev Emitted when positions are successfully merged.
    event PositionsMerge(
        address indexed stakeholder,
        IERC20 collateralToken,
        bytes32 indexed parentCollectionId,
        bytes32 indexed conditionId,
        uint[] partition,
        uint amount
    );
    event PayoutRedemption(
        address indexed redeemer,
        IERC20 indexed collateralToken,
        bytes32 indexed parentCollectionId,
        bytes32 conditionId,
        uint[] indexSets,
        uint payout
    );


    /// Mapping key is an condition ID. Value represents numerators of the payout vector associated with the condition. This array is initialized with a length equal to the outcome slot count. E.g. Condition with 3 outcomes [A, B, C] and two of those correct [0.5, 0.5, 0]. In Ethereum there are no decimal values, so here, 0.5 is represented by fractions like 1/2 == 0.5. That's why we need numerator and denominator values. Payout numerators are also used as a check of initialization. If the numerators array is empty (has length zero), the condition was not created/prepared. See getOutcomeSlotCount.
    mapping(bytes32 => uint[]) public payoutNumerators;
    /// Denominator is also used for checking if the condition has been resolved. If the denominator is non-zero, then the condition has been resolved.
    mapping(bytes32 => uint) public payoutDenominator;

    /// @dev This function prepares a condition by initializing a payout vector associated with the condition.
    /// @param oracle The account assigned to report the result for the prepared condition.
    /// @param questionId An identifier for the question to be answered by the oracle.
    /// @param outcomeSlotCount The number of outcome slots which should be used for this condition. Must not exceed 256.
    function prepareCondition(address oracle, bytes32 questionId, uint outcomeSlotCount) external {
        // Limit of 256 because we use a partition array that is a number of 256 bits.
        require(outcomeSlotCount <= 256, "too many outcome slots");
        require(outcomeSlotCount > 1, "there should be more than one outcome slot");
        bytes32 conditionId = CTHelpers.getConditionId(oracle, questionId, outcomeSlotCount);
        require(payoutNumerators[conditionId].length == 0, "condition already prepared");
        payoutNumerators[conditionId] = new uint[](outcomeSlotCount);
        emit ConditionPreparation(conditionId, oracle, questionId, outcomeSlotCount);
    }

    /// @dev Called by the oracle for reporting results of conditions. Will set the payout vector for the condition with the ID ``keccak256(abi.encodePacked(oracle, questionId, outcomeSlotCount))``, where oracle is the message sender, questionId is one of the parameters of this function, and outcomeSlotCount is the length of the payouts parameter, which contains the payoutNumerators for each outcome slot of the condition.
    /// @param questionId The question ID the oracle is answering for
    /// @param payouts The oracle's answer
    function reportPayouts(bytes32 questionId, uint[] calldata payouts) external {
        uint outcomeSlotCount = payouts.length;
        require(outcomeSlotCount > 1, "there should be more than one outcome slot");
        // IMPORTANT, the oracle is enforced to be the sender because it's part of the hash.
        bytes32 conditionId = CTHelpers.getConditionId(msg.sender, questionId, outcomeSlotCount);
        require(payoutNumerators[conditionId].length == outcomeSlotCount, "condition not prepared or found");
        require(payoutDenominator[conditionId] == 0, "payout denominator already set");

        uint den = 0;
        for (uint i = 0; i < outcomeSlotCount; i++) {
            uint num = payouts[i];
            den = den.add(num);

            require(payoutNumerators[conditionId][i] == 0, "payout numerator already set");
            payoutNumerators[conditionId][i] = num;
        }
        require(den > 0, "payout is all zeroes");
        payoutDenominator[conditionId] = den;
        emit ConditionResolution(conditionId, msg.sender, questionId, outcomeSlotCount, payoutNumerators[conditionId]);
    }

    /// @dev This function splits a position. If splitting from the collateral, this contract will attempt to transfer `amount` collateral from the message sender to itself. Otherwise, this contract will burn `amount` stake held by the message sender in the position being split worth of EIP 1155 tokens. Regardless, if successful, `amount` stake will be minted in the split target positions. If any of the transfers, mints, or burns fail, the transaction will revert. The transaction will also revert if the given partition is trivial, invalid, or refers to more slots than the condition is prepared with.
    /// @param collateralToken The address of the positions' backing collateral token.
    /// @param parentCollectionId The ID of the outcome collections common to the position being split and the split target positions. May be null, in which only the collateral is shared.
    /// @param conditionId The ID of the condition to split on.
    /// @param partition An array of disjoint index sets representing a nontrivial partition of the outcome slots of the given condition. E.g. A|B and C but not A|B and B|C (is not disjoint). Each element's a number which, together with the condition, represents the outcome collection. E.g. 0b110 is A|B, 0b010 is B, etc.
    /// @param amount The amount of collateral or stake to split.
    function splitPosition(
        IERC20 collateralToken,
        bytes32 parentCollectionId,
        bytes32 conditionId,
        uint[] calldata partition,
        uint amount
    ) external {
        require(partition.length > 1, "got empty or singleton partition");
        uint outcomeSlotCount = payoutNumerators[conditionId].length;
        require(outcomeSlotCount > 0, "condition not prepared yet");

        // For a condition with 4 outcomes fullIndexSet's 0b1111; for 5 it's 0b11111...
        uint fullIndexSet = (1 << outcomeSlotCount) - 1;
        // freeIndexSet starts as the full collection
        uint freeIndexSet = fullIndexSet;
        // This loop checks that all condition sets are disjoint (the same outcome is not part of more than 1 set)
        uint[] memory positionIds = new uint[](partition.length);
        uint[] memory amounts = new uint[](partition.length);
        for (uint i = 0; i < partition.length; i++) {
            uint indexSet = partition[i];
            require(indexSet > 0 && indexSet < fullIndexSet, "got invalid index set");
            require((indexSet & freeIndexSet) == indexSet, "partition not disjoint");
            freeIndexSet ^= indexSet;
            positionIds[i] = CTHelpers.getPositionId(collateralToken, CTHelpers.getCollectionId(parentCollectionId, conditionId, indexSet));
            amounts[i] = amount;
        }

        if (freeIndexSet == 0) {
            // Partitioning the full set of outcomes for the condition in this branch
            if (parentCollectionId == bytes32(0)) {
                require(collateralToken.transferFrom(msg.sender, address(this), amount), "could not receive collateral tokens");
            } else {
                _burn(
                    msg.sender,
                    CTHelpers.getPositionId(collateralToken, parentCollectionId),
                    amount
                );
            }
        } else {
            // Partitioning a subset of outcomes for the condition in this branch.
            // For example, for a condition with three outcomes A, B, and C, this branch
            // allows the splitting of a position $:(A|C) to positions $:(A) and $:(C).
            _burn(
                msg.sender,
                CTHelpers.getPositionId(collateralToken,
                    CTHelpers.getCollectionId(parentCollectionId, conditionId, fullIndexSet ^ freeIndexSet)),
                amount
            );
        }

        _batchMint(
            msg.sender,
            // position ID is the ERC 1155 token ID
            positionIds,
            amounts,
            ""
        );
        emit PositionSplit(msg.sender, collateralToken, parentCollectionId, conditionId, partition, amount);
    }

    function mergePositions(
        IERC20 collateralToken,
        bytes32 parentCollectionId,
        bytes32 conditionId,
        uint[] calldata partition,
        uint amount
    ) external {
        require(partition.length > 1, "got empty or singleton partition");
        uint outcomeSlotCount = payoutNumerators[conditionId].length;
        require(outcomeSlotCount > 0, "condition not prepared yet");

        uint fullIndexSet = (1 << outcomeSlotCount) - 1;
        uint freeIndexSet = fullIndexSet;
        uint[] memory positionIds = new uint[](partition.length);
        uint[] memory amounts = new uint[](partition.length);
        for (uint i = 0; i < partition.length; i++) {
            uint indexSet = partition[i];
            require(indexSet > 0 && indexSet < fullIndexSet, "got invalid index set");
            require((indexSet & freeIndexSet) == indexSet, "partition not disjoint");
            freeIndexSet ^= indexSet;
            positionIds[i] = CTHelpers.getPositionId(collateralToken, CTHelpers.getCollectionId(parentCollectionId, conditionId, indexSet));
            amounts[i] = amount;
        }
        _batchBurn(
            msg.sender,
            positionIds,
            amounts
        );

        if (freeIndexSet == 0) {
            if (parentCollectionId == bytes32(0)) {
                require(collateralToken.transfer(msg.sender, amount), "could not send collateral tokens");
            } else {
                _mint(
                    msg.sender,
                    CTHelpers.getPositionId(collateralToken, parentCollectionId),
                    amount,
                    ""
                );
            }
        } else {
            _mint(
                msg.sender,
                CTHelpers.getPositionId(collateralToken,
                    CTHelpers.getCollectionId(parentCollectionId, conditionId, fullIndexSet ^ freeIndexSet)),
                amount,
                ""
            );
        }

        emit PositionsMerge(msg.sender, collateralToken, parentCollectionId, conditionId, partition, amount);
    }

    function redeemPositions(IERC20 collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint[] calldata indexSets) external {
        uint den = payoutDenominator[conditionId];
        require(den > 0, "result for condition not received yet");
        uint outcomeSlotCount = payoutNumerators[conditionId].length;
        require(outcomeSlotCount > 0, "condition not prepared yet");

        uint totalPayout = 0;

        uint fullIndexSet = (1 << outcomeSlotCount) - 1;
        for (uint i = 0; i < indexSets.length; i++) {
            uint indexSet = indexSets[i];
            require(indexSet > 0 && indexSet < fullIndexSet, "got invalid index set");
            uint positionId = CTHelpers.getPositionId(collateralToken,
                CTHelpers.getCollectionId(parentCollectionId, conditionId, indexSet));

            uint payoutNumerator = 0;
            for (uint j = 0; j < outcomeSlotCount; j++) {
                if (indexSet & (1 << j) != 0) {
                    payoutNumerator = payoutNumerator.add(payoutNumerators[conditionId][j]);
                }
            }

            uint payoutStake = balanceOf(msg.sender, positionId);
            if (payoutStake > 0) {
                totalPayout = totalPayout.add(payoutStake.mul(payoutNumerator).div(den));
                _burn(msg.sender, positionId, payoutStake);
            }
        }

        if (totalPayout > 0) {
            if (parentCollectionId == bytes32(0)) {
                require(collateralToken.transfer(msg.sender, totalPayout), "could not transfer payout to message sender");
            } else {
                _mint(msg.sender, CTHelpers.getPositionId(collateralToken, parentCollectionId), totalPayout, "");
            }
        }
        emit PayoutRedemption(msg.sender, collateralToken, parentCollectionId, conditionId, indexSets, totalPayout);
    }

    /// @dev Gets the outcome slot count of a condition.
    /// @param conditionId ID of the condition.
    /// @return Number of outcome slots associated with a condition, or zero if condition has not been prepared yet.
    function getOutcomeSlotCount(bytes32 conditionId) external view returns (uint) {
        return payoutNumerators[conditionId].length;
    }

    /// @dev Constructs a condition ID from an oracle, a question ID, and the outcome slot count for the question.
    /// @param oracle The account assigned to report the result for the prepared condition.
    /// @param questionId An identifier for the question to be answered by the oracle.
    /// @param outcomeSlotCount The number of outcome slots which should be used for this condition. Must not exceed 256.
    function getConditionId(address oracle, bytes32 questionId, uint outcomeSlotCount) external pure returns (bytes32) {
        return CTHelpers.getConditionId(oracle, questionId, outcomeSlotCount);
    }

    /// @dev Constructs an outcome collection ID from a parent collection and an outcome collection.
    /// @param parentCollectionId Collection ID of the parent outcome collection, or bytes32(0) if there's no parent.
    /// @param conditionId Condition ID of the outcome collection to combine with the parent outcome collection.
    /// @param indexSet Index set of the outcome collection to combine with the parent outcome collection.
    function getCollectionId(bytes32 parentCollectionId, bytes32 conditionId, uint indexSet) external view returns (bytes32) {
        return CTHelpers.getCollectionId(parentCollectionId, conditionId, indexSet);
    }

    /// @dev Constructs a position ID from a collateral token and an outcome collection. These IDs are used as the ERC-1155 ID for this contract.
    /// @param collateralToken Collateral token which backs the position.
    /// @param collectionId ID of the outcome collection associated with this position.
    function getPositionId(IERC20 collateralToken, bytes32 collectionId) external pure returns (uint) {
        return CTHelpers.getPositionId(collateralToken, collectionId);
    }
}


// File @gnosis.pm/conditional-tokens-contracts/contracts/ERC1155/[email protected]

pragma solidity ^0.5.0;


contract ERC1155TokenReceiver is ERC165, IERC1155TokenReceiver {
    constructor() public {
        _registerInterface(
            ERC1155TokenReceiver(0).onERC1155Received.selector ^
            ERC1155TokenReceiver(0).onERC1155BatchReceived.selector
        );
    }
}


// File contracts/FixedProductMarketMaker.sol

pragma solidity ^0.5.1;






library CeilDiv {
    // calculates ceil(x/y)
    function ceildiv(uint x, uint y) internal pure returns (uint) {
        if(x > 0) return ((x - 1) / y) + 1;
        return x / y;
    }
}


contract FixedProductMarketMaker is ERC20, ERC1155TokenReceiver {
    event FPMMFundingAdded(
        address indexed funder,
        uint[] amountsAdded,
        uint sharesMinted
    );
    event FPMMFundingRemoved(
        address indexed funder,
        uint[] amountsRemoved,
        uint collateralRemovedFromFeePool,
        uint sharesBurnt
    );
    event FPMMBuy(
        address indexed buyer,
        uint investmentAmount,
        uint feeAmount,
        uint indexed outcomeIndex,
        uint outcomeTokensBought
    );
    event FPMMSell(
        address indexed seller,
        uint returnAmount,
        uint feeAmount,
        uint indexed outcomeIndex,
        uint outcomeTokensSold
    );

    using SafeMath for uint;
    using CeilDiv for uint;

    uint constant ONE = 10**18;

    ConditionalTokens public conditionalTokens;
    IERC20 public collateralToken;
    bytes32[] public conditionIds;
    uint public fee;
    uint internal feePoolWeight;

    uint[] outcomeSlotCounts;
    bytes32[][] collectionIds;
    uint[] positionIds;
    mapping (address => uint256) withdrawnFees;
    uint internal totalWithdrawnFees;

    function getPoolBalances() private view returns (uint[] memory) {
        address[] memory thises = new address[](positionIds.length);
        for(uint i = 0; i < positionIds.length; i++) {
            thises[i] = address(this);
        }
        return conditionalTokens.balanceOfBatch(thises, positionIds);
    }

    function generateBasicPartition(uint outcomeSlotCount)
        private
        pure
        returns (uint[] memory partition)
    {
        partition = new uint[](outcomeSlotCount);
        for(uint i = 0; i < outcomeSlotCount; i++) {
            partition[i] = 1 << i;
        }
    }

    function splitPositionThroughAllConditions(uint amount)
        private
    {
        for(uint i = conditionIds.length - 1; int(i) >= 0; i--) {
            uint[] memory partition = generateBasicPartition(outcomeSlotCounts[i]);
            for(uint j = 0; j < collectionIds[i].length; j++) {
                conditionalTokens.splitPosition(collateralToken, collectionIds[i][j], conditionIds[i], partition, amount);
            }
        }
    }

    function mergePositionsThroughAllConditions(uint amount)
        private
    {
        for(uint i = 0; i < conditionIds.length; i++) {
            uint[] memory partition = generateBasicPartition(outcomeSlotCounts[i]);
            for(uint j = 0; j < collectionIds[i].length; j++) {
                conditionalTokens.mergePositions(collateralToken, collectionIds[i][j], conditionIds[i], partition, amount);
            }
        }
    }

    function collectedFees() external view returns (uint) {
        return feePoolWeight.sub(totalWithdrawnFees);
    }

    function feesWithdrawableBy(address account) public view returns (uint) {
        uint rawAmount = feePoolWeight.mul(balanceOf(account)) / totalSupply();
        return rawAmount.sub(withdrawnFees[account]);
    }

    function withdrawFees(address account) public {
        uint rawAmount = feePoolWeight.mul(balanceOf(account)) / totalSupply();
        uint withdrawableAmount = rawAmount.sub(withdrawnFees[account]);
        if(withdrawableAmount > 0){
            withdrawnFees[account] = rawAmount;
            totalWithdrawnFees = totalWithdrawnFees.add(withdrawableAmount);
            require(collateralToken.transfer(account, withdrawableAmount), "withdrawal transfer failed");
        }
    }

    function _beforeTokenTransfer(address from, address to, uint256 amount) internal {
        if (from != address(0)) {
            withdrawFees(from);
        }

        uint totalSupply = totalSupply();
        uint withdrawnFeesTransfer = totalSupply == 0 ?
            amount :
            feePoolWeight.mul(amount) / totalSupply;

        if (from != address(0)) {
            withdrawnFees[from] = withdrawnFees[from].sub(withdrawnFeesTransfer);
            totalWithdrawnFees = totalWithdrawnFees.sub(withdrawnFeesTransfer);
        } else {
            feePoolWeight = feePoolWeight.add(withdrawnFeesTransfer);
        }
        if (to != address(0)) {
            withdrawnFees[to] = withdrawnFees[to].add(withdrawnFeesTransfer);
            totalWithdrawnFees = totalWithdrawnFees.add(withdrawnFeesTransfer);
        } else {
            feePoolWeight = feePoolWeight.sub(withdrawnFeesTransfer);
        }
    }

    function addFunding(uint addedFunds, uint[] calldata distributionHint)
        external
    {
        require(addedFunds > 0, "funding must be non-zero");

        uint[] memory sendBackAmounts = new uint[](positionIds.length);
        uint poolShareSupply = totalSupply();
        uint mintAmount;
        if(poolShareSupply > 0) {
            require(distributionHint.length == 0, "cannot use distribution hint after initial funding");
            uint[] memory poolBalances = getPoolBalances();
            uint poolWeight = 0;
            for(uint i = 0; i < poolBalances.length; i++) {
                uint balance = poolBalances[i];
                if(poolWeight < balance)
                    poolWeight = balance;
            }

            for(uint i = 0; i < poolBalances.length; i++) {
                uint remaining = addedFunds.mul(poolBalances[i]) / poolWeight;
                sendBackAmounts[i] = addedFunds.sub(remaining);
            }

            mintAmount = addedFunds.mul(poolShareSupply) / poolWeight;
        } else {
            if(distributionHint.length > 0) {
                require(distributionHint.length == positionIds.length, "hint length off");
                uint maxHint = 0;
                for(uint i = 0; i < distributionHint.length; i++) {
                    uint hint = distributionHint[i];
                    if(maxHint < hint)
                        maxHint = hint;
                }

                for(uint i = 0; i < distributionHint.length; i++) {
                    uint remaining = addedFunds.mul(distributionHint[i]) / maxHint;
                    require(remaining > 0, "must hint a valid distribution");
                    sendBackAmounts[i] = addedFunds.sub(remaining);
                }
            }

            mintAmount = addedFunds;
        }

        require(collateralToken.transferFrom(msg.sender, address(this), addedFunds), "funding transfer failed");
        require(collateralToken.approve(address(conditionalTokens), addedFunds), "approval for splits failed");
        splitPositionThroughAllConditions(addedFunds);

        _mint(msg.sender, mintAmount);

        conditionalTokens.safeBatchTransferFrom(address(this), msg.sender, positionIds, sendBackAmounts, "");

        // transform sendBackAmounts to array of amounts added
        for (uint i = 0; i < sendBackAmounts.length; i++) {
            sendBackAmounts[i] = addedFunds.sub(sendBackAmounts[i]);
        }

        emit FPMMFundingAdded(msg.sender, sendBackAmounts, mintAmount);
    }

    function removeFunding(uint sharesToBurn)
        external
    {
        uint[] memory poolBalances = getPoolBalances();

        uint[] memory sendAmounts = new uint[](poolBalances.length);

        uint poolShareSupply = totalSupply();
        for(uint i = 0; i < poolBalances.length; i++) {
            sendAmounts[i] = poolBalances[i].mul(sharesToBurn) / poolShareSupply;
        }

        uint collateralRemovedFromFeePool = collateralToken.balanceOf(address(this));

        _burn(msg.sender, sharesToBurn);
        collateralRemovedFromFeePool = collateralRemovedFromFeePool.sub(
            collateralToken.balanceOf(address(this))
        );

        conditionalTokens.safeBatchTransferFrom(address(this), msg.sender, positionIds, sendAmounts, "");

        emit FPMMFundingRemoved(msg.sender, sendAmounts, collateralRemovedFromFeePool, sharesToBurn);
    }

    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    )
        external
        returns (bytes4)
    {
        if (operator == address(this)) {
            return this.onERC1155Received.selector;
        }
        return 0x0;
    }

    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    )
        external
        returns (bytes4)
    {
        if (operator == address(this) && from == address(0)) {
            return this.onERC1155BatchReceived.selector;
        }
        return 0x0;
    }

    function calcBuyAmount(uint investmentAmount, uint outcomeIndex) public view returns (uint) {
        require(outcomeIndex < positionIds.length, "invalid outcome index");

        uint[] memory poolBalances = getPoolBalances();
        uint investmentAmountMinusFees = investmentAmount.sub(investmentAmount.mul(fee) / ONE);
        uint buyTokenPoolBalance = poolBalances[outcomeIndex];
        uint endingOutcomeBalance = buyTokenPoolBalance.mul(ONE);
        for(uint i = 0; i < poolBalances.length; i++) {
            if(i != outcomeIndex) {
                uint poolBalance = poolBalances[i];
                endingOutcomeBalance = endingOutcomeBalance.mul(poolBalance).ceildiv(
                    poolBalance.add(investmentAmountMinusFees)
                );
            }
        }
        require(endingOutcomeBalance > 0, "must have non-zero balances");

        return buyTokenPoolBalance.add(investmentAmountMinusFees).sub(endingOutcomeBalance.ceildiv(ONE));
    }

    function calcSellAmount(uint returnAmount, uint outcomeIndex) public view returns (uint outcomeTokenSellAmount) {
        require(outcomeIndex < positionIds.length, "invalid outcome index");

        uint[] memory poolBalances = getPoolBalances();
        uint returnAmountPlusFees = returnAmount.mul(ONE) / ONE.sub(fee);
        uint sellTokenPoolBalance = poolBalances[outcomeIndex];
        uint endingOutcomeBalance = sellTokenPoolBalance.mul(ONE);
        for(uint i = 0; i < poolBalances.length; i++) {
            if(i != outcomeIndex) {
                uint poolBalance = poolBalances[i];
                endingOutcomeBalance = endingOutcomeBalance.mul(poolBalance).ceildiv(
                    poolBalance.sub(returnAmountPlusFees)
                );
            }
        }
        require(endingOutcomeBalance > 0, "must have non-zero balances");

        return returnAmountPlusFees.add(endingOutcomeBalance.ceildiv(ONE)).sub(sellTokenPoolBalance);
    }

    function buy(uint investmentAmount, uint outcomeIndex, uint minOutcomeTokensToBuy) external {
        uint outcomeTokensToBuy = calcBuyAmount(investmentAmount, outcomeIndex);
        require(outcomeTokensToBuy >= minOutcomeTokensToBuy, "minimum buy amount not reached");

        require(collateralToken.transferFrom(msg.sender, address(this), investmentAmount), "cost transfer failed");

        uint feeAmount = investmentAmount.mul(fee) / ONE;
        feePoolWeight = feePoolWeight.add(feeAmount);
        uint investmentAmountMinusFees = investmentAmount.sub(feeAmount);
        require(collateralToken.approve(address(conditionalTokens), investmentAmountMinusFees), "approval for splits failed");
        splitPositionThroughAllConditions(investmentAmountMinusFees);

        conditionalTokens.safeTransferFrom(address(this), msg.sender, positionIds[outcomeIndex], outcomeTokensToBuy, "");

        emit FPMMBuy(msg.sender, investmentAmount, feeAmount, outcomeIndex, outcomeTokensToBuy);
    }

    function sell(uint returnAmount, uint outcomeIndex, uint maxOutcomeTokensToSell) external {
        uint outcomeTokensToSell = calcSellAmount(returnAmount, outcomeIndex);
        require(outcomeTokensToSell <= maxOutcomeTokensToSell, "maximum sell amount exceeded");

        conditionalTokens.safeTransferFrom(msg.sender, address(this), positionIds[outcomeIndex], outcomeTokensToSell, "");

        uint feeAmount = returnAmount.mul(fee) / (ONE.sub(fee));
        feePoolWeight = feePoolWeight.add(feeAmount);
        uint returnAmountPlusFees = returnAmount.add(feeAmount);
        mergePositionsThroughAllConditions(returnAmountPlusFees);

        require(collateralToken.transfer(msg.sender, returnAmount), "return transfer failed");

        emit FPMMSell(msg.sender, returnAmount, feeAmount, outcomeIndex, outcomeTokensToSell);
    }
}


// for proxying purposes
contract FixedProductMarketMakerData {
    mapping (address => uint256) internal _balances;
    mapping (address => mapping (address => uint256)) internal _allowances;
    uint256 internal _totalSupply;


    bytes4 internal constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
    mapping(bytes4 => bool) internal _supportedInterfaces;


    event FPMMFundingAdded(
        address indexed funder,
        uint[] amountsAdded,
        uint sharesMinted
    );
    event FPMMFundingRemoved(
        address indexed funder,
        uint[] amountsRemoved,
        uint collateralRemovedFromFeePool,
        uint sharesBurnt
    );
    event FPMMBuy(
        address indexed buyer,
        uint investmentAmount,
        uint feeAmount,
        uint indexed outcomeIndex,
        uint outcomeTokensBought
    );
    event FPMMSell(
        address indexed seller,
        uint returnAmount,
        uint feeAmount,
        uint indexed outcomeIndex,
        uint outcomeTokensSold
    );
    ConditionalTokens internal conditionalTokens;
    IERC20 internal collateralToken;
    bytes32[] internal conditionIds;
    uint internal fee;
    uint internal feePoolWeight;

    uint[] internal outcomeSlotCounts;
    bytes32[][] internal collectionIds;
    uint[] internal positionIds;
    mapping (address => uint256) internal withdrawnFees;
    uint internal totalWithdrawnFees;
}


// File @gnosis.pm/util-contracts/contracts/[email protected]

pragma solidity >=0.4.24 ^0.5.1;

contract ConstructedCloneFactory {

    event CloneCreated(address indexed target, address clone);
    
    function cloneConstructor(bytes calldata) external;

    function createClone(address target, bytes memory consData) internal returns (address result) {
        bytes memory consPayload = abi.encodeWithSignature("cloneConstructor(bytes)", consData);
        bytes memory clone = new bytes(consPayload.length + 99);
        
        assembly {
            mstore(add(clone, 0x20),
                0x3d3d606380380380913d393d73bebebebebebebebebebebebebebebebebebebe)
            mstore(add(clone, 0x2d),
                mul(address, 0x01000000000000000000000000))
            mstore(add(clone, 0x41),
                0x5af4602a57600080fd5b602d8060366000396000f3363d3d373d3d3d363d73be)
            mstore(add(clone, 0x60),
                mul(target, 0x01000000000000000000000000))
            mstore(add(clone, 116),
                0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
        }
        
        for(uint i = 0; i < consPayload.length; i++) {
            clone[99 + i] = consPayload[i];
        }

        assembly {
          let len := mload(clone)
          let data := add(clone, 0x20)
          result := create(0, data, len)
        }
        
        require(result != address(0));
    }
}


// File contracts/FixedProductMarketMakerFactory.sol

pragma solidity ^0.5.1;






contract FixedProductMarketMakerFactory is ConstructedCloneFactory, FixedProductMarketMakerData {
    event FixedProductMarketMakerCreation(
        address indexed creator,
        FixedProductMarketMaker fixedProductMarketMaker,
        ConditionalTokens indexed conditionalTokens,
        IERC20 indexed collateralToken,
        bytes32[] conditionIds,
        uint fee
    );

    FixedProductMarketMaker public implementationMaster;

    constructor() public {
        implementationMaster = new FixedProductMarketMaker();
    }

    function cloneConstructor(bytes calldata consData) external {
        (
            ConditionalTokens _conditionalTokens,
            IERC20 _collateralToken,
            bytes32[] memory _conditionIds,
            uint _fee
        ) = abi.decode(consData, (ConditionalTokens, IERC20, bytes32[], uint));

        _supportedInterfaces[_INTERFACE_ID_ERC165] = true;
        _supportedInterfaces[
            ERC1155TokenReceiver(0).onERC1155Received.selector ^
            ERC1155TokenReceiver(0).onERC1155BatchReceived.selector
        ] = true;

        conditionalTokens = _conditionalTokens;
        collateralToken = _collateralToken;
        conditionIds = _conditionIds;
        fee = _fee;

        uint atomicOutcomeSlotCount = 1;
        outcomeSlotCounts = new uint[](conditionIds.length);
        for (uint i = 0; i < conditionIds.length; i++) {
            uint outcomeSlotCount = conditionalTokens.getOutcomeSlotCount(conditionIds[i]);
            atomicOutcomeSlotCount *= outcomeSlotCount;
            outcomeSlotCounts[i] = outcomeSlotCount;
        }
        require(atomicOutcomeSlotCount > 1, "conditions must be valid");

        collectionIds = new bytes32[][](conditionIds.length);
        _recordCollectionIDsForAllConditions(conditionIds.length, bytes32(0));
        require(positionIds.length == atomicOutcomeSlotCount, "position IDs construction failed!?");
    }

    function _recordCollectionIDsForAllConditions(uint conditionsLeft, bytes32 parentCollectionId) private {
        if(conditionsLeft == 0) {
            positionIds.push(CTHelpers.getPositionId(collateralToken, parentCollectionId));
            return;
        }

        conditionsLeft--;

        uint outcomeSlotCount = outcomeSlotCounts[conditionsLeft];

        collectionIds[conditionsLeft].push(parentCollectionId);
        for(uint i = 0; i < outcomeSlotCount; i++) {
            _recordCollectionIDsForAllConditions(
                conditionsLeft,
                CTHelpers.getCollectionId(
                    parentCollectionId,
                    conditionIds[conditionsLeft],
                    1 << i
                )
            );
        }
    }

    function createFixedProductMarketMaker(
        ConditionalTokens conditionalTokens,
        IERC20 collateralToken,
        bytes32[] calldata conditionIds,
        uint fee
    )
        external
        returns (FixedProductMarketMaker)
    {
        FixedProductMarketMaker fixedProductMarketMaker = FixedProductMarketMaker(
            createClone(address(implementationMaster), abi.encode(
                conditionalTokens,
                collateralToken,
                conditionIds,
                fee
            ))
        );
        emit FixedProductMarketMakerCreation(
            msg.sender,
            fixedProductMarketMaker,
            conditionalTokens,
            collateralToken,
            conditionIds,
            fee
        );
        return fixedProductMarketMaker;
    }
}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[],"name":"implementationMaster","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"conditionalTokens","type":"address"},{"name":"collateralToken","type":"address"},{"name":"conditionIds","type":"bytes32[]"},{"name":"fee","type":"uint256"}],"name":"createFixedProductMarketMaker","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"consData","type":"bytes"}],"name":"cloneConstructor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"creator","type":"address"},{"indexed":false,"name":"fixedProductMarketMaker","type":"address"},{"indexed":true,"name":"conditionalTokens","type":"address"},{"indexed":true,"name":"collateralToken","type":"address"},{"indexed":false,"name":"conditionIds","type":"bytes32[]"},{"indexed":false,"name":"fee","type":"uint256"}],"name":"FixedProductMarketMakerCreation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"funder","type":"address"},{"indexed":false,"name":"amountsAdded","type":"uint256[]"},{"indexed":false,"name":"sharesMinted","type":"uint256"}],"name":"FPMMFundingAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"funder","type":"address"},{"indexed":false,"name":"amountsRemoved","type":"uint256[]"},{"indexed":false,"name":"collateralRemovedFromFeePool","type":"uint256"},{"indexed":false,"name":"sharesBurnt","type":"uint256"}],"name":"FPMMFundingRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"buyer","type":"address"},{"indexed":false,"name":"investmentAmount","type":"uint256"},{"indexed":false,"name":"feeAmount","type":"uint256"},{"indexed":true,"name":"outcomeIndex","type":"uint256"},{"indexed":false,"name":"outcomeTokensBought","type":"uint256"}],"name":"FPMMBuy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"seller","type":"address"},{"indexed":false,"name":"returnAmount","type":"uint256"},{"indexed":false,"name":"feeAmount","type":"uint256"},{"indexed":true,"name":"outcomeIndex","type":"uint256"},{"indexed":false,"name":"outcomeTokensSold","type":"uint256"}],"name":"FPMMSell","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"target","type":"address"},{"indexed":false,"name":"clone","type":"address"}],"name":"CloneCreated","type":"event"}]

608060405234801561001057600080fd5b5060405161001d9061005f565b604051809103906000f080158015610039573d6000803e3d6000fd5b50600e80546001600160a01b0319166001600160a01b039290921691909117905561006c565b612d09806115f983390190565b61157e8061007b6000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806312b4d20c1461004657806323f66e471461006a57806352e831dd146100f3575b600080fd5b61004e610165565b604080516001600160a01b039092168252519081900360200190f35b61004e6004803603608081101561008057600080fd5b6001600160a01b0382358116926020810135909116918101906060810160408201356401000000008111156100b457600080fd5b8201836020820111156100c657600080fd5b803590602001918460208302840111640100000000831117156100e857600080fd5b919350915035610174565b6101636004803603602081101561010957600080fd5b81019060208101813564010000000081111561012457600080fd5b82018360208201111561013657600080fd5b8035906020019184600183028401116401000000008311171561015857600080fd5b5090925090506102cf565b005b600e546001600160a01b031681565b600080610220600e60009054906101000a90046001600160a01b0316888888888860405160200180866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b03168152602001806020018381526020018281038252858582818152602001925060200280828437600081840152601f19601f820116905080830192505050965050505050505060405160208183030381529060405261064a565b9050856001600160a01b0316876001600160a01b0316336001600160a01b03167f92e0912d3d7f3192cad5c7ae3b47fb97f9c465c1dd12a5c24fd901ddb3905f438489898960405180856001600160a01b03166001600160a01b03168152602001806020018381526020018281038252858582818152602001925060200280828437600083820152604051601f909101601f191690920182900397509095505050505050a49695505050505050565b60008060606000858560808110156102e657600080fd5b6001600160a01b03823581169260208101359091169181019060608101604082013564010000000081111561031a57600080fd5b82018360208201111561032c57600080fd5b8035906020019184602083028401116401000000008311171561034e57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250600360209081527f28b0ef64f7e82d3b26f3fd404bd0151552f792965f39c29ae82c0a78df67af9c805460ff199081166001908117909255630271189760e51b9093527f1b0a8c8743953bd832c9e1d6a5e52d4143b336fe3e4824afb8e5e7621b19f90b805490931617909155600480546001600160a01b03808d166001600160a01b03199283161790925560058054928c16929091169190911790558451999d50979b50929950509135965061043f95600695890194509250611402915050565b5060078190556006546040805182815260208084028201019091526001918015610473578160200160208202803883390190505b50805161048891600991602090910190611402565b5060005b60065481101561055157600454600680546000926001600160a01b03169163d42dc0c291859081106104ba57fe5b90600052602060002001546040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156104f957600080fd5b505afa15801561050d573d6000803e3d6000fd5b505050506040513d602081101561052357600080fd5b5051600980549482029491925082918490811061053c57fe5b6000918252602090912001555060010161048c565b50600181116105a7576040805162461bcd60e51b815260206004820152601860248201527f636f6e646974696f6e73206d7573742062652076616c69640000000000000000604482015290519081900360640190fd5b6006546040805182815260208084028201019091529080156105dd57816020015b60608152602001906001900390816105c85790505b5080516105f291600a9160209091019061144d565b50600654610601906000610819565b600b5481146106415760405162461bcd60e51b81526004018080602001828103825260228152602001806115286022913960400191505060405180910390fd5b50505050505050565b60006060826040516024018080602001828103825283818151815260200191508051906020019080838360005b8381101561068f578181015183820152602001610677565b50505050905090810190601f1680156106bc5780820380516001836020036101000a031916815260200191505b5060408051601f1981840381018252928252602080820180516001600160e01b03166352e831dd60e01b17905281518351606382018082526082909201909516850190910190925295506060945090925090508015610722576020820181803883390190505b507f3d3d606380380380913d393d73bebebebebebebebebebebebebebebebebebebe6020820152600160601b308102602d8301527f5af4602a57600080fd5b602d8060366000396000f3363d3d373d3d3d363d73be6041830152860260608201526e5af43d82803e903d91602b57fd5bf360881b6074820152905060005b82518110156107ee578281815181106107b557fe5b602001015160f81c60f81b8282606301815181106107cf57fe5b60200101906001600160f81b031916908160001a9053506001016107a0565b5080516020820181816000f0945050506001600160a01b03831661081157600080fd5b505092915050565b8161085257600554600b90610837906001600160a01b0316836108ea565b815460018101835560009283526020909220909101556108e6565b81806001900392505060006009838154811061086a57fe5b90600052602060002001549050600a838154811061088457fe5b600091825260208083209091018054600181018255908352908220018390555b818110156108e3576108db846108d685600688815481106108c157fe5b9060005260206000200154856001901b61092e565b610819565b6001016108a4565b50505b5050565b6040805160609390931b6bffffffffffffffffffffffff19166020808501919091526034808501939093528151808503909301835260549093019052805191012090565b6040805160208082018590528183018490528251808303840181526060909201909252805191012060009060ff81901c151582805b60008051602061150883398151915260018508935060008051602061150883398151915260036000805160206115088339815191528087880987090890506109aa81610c5d565b9150806000805160206115088339815191528384091415610963578280156109d3575060028206155b806109ea5750821580156109ea5750600282066001145b15610a0357816000805160206115088339815191520391505b878015610c3a5760fe81901c151593506001600160fe1b031660008051602061150883398151915260036000805160206115088339815191528084850984090891506000610a5083610c5d565b9050848015610a60575060028106155b80610a77575084158015610a775750600281066001145b15610a8d57600080516020611508833981519152035b8260008051602061150883398151915282830914610af2576040805162461bcd60e51b815260206004820152601c60248201527f696e76616c696420706172656e7420636f6c6c656374696f6e20494400000000604482015290519081900360640190fd5b6000606060066001600160a01b031688878686604051602001808581526020018481526020018381526020018281526020019450505050506040516020818303038152906040526040518082805190602001908083835b60208310610b685780518252601f199092019160209182019101610b49565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114610bc8576040519150601f19603f3d011682016040523d82523d6000602084013e610bcd565b606091505b509150915081610c13576040805162461bcd60e51b815260206004820152600c60248201526b1958d859190819985a5b195960a21b604482015290519081900360640190fd5b808060200190516040811015610c2857600080fd5b50805160209091015190985095505050505b6002830660011415610c5057600160fe1b851894505b5092979650505050505050565b6000600080516020611508833981519152808380099150808283098181820990508181840992508183850993508184840992508183840990508181820982818309905082818209905082818209905082818309915082828609945082858609915082828309915082828509935082848509915082828309915082828309915082828509915082828609945082858609915082828309915082828309915082828609915082828509935082848609945082858609915082828309915082828509935082848509915082828309905082818209905082818209905082818309915082828609945082858509935082848509915082828309915082828309915082828609945082858609915082828309915082828609915082828309915082828309915082828609915082828509935082848509915082828309905082818209905082818309905082818509905082818209905082818209905082818209905082818209905082818309915082828609945082858609915082828609915082828509935082848509915082828509915082828309915082828309905082818309905082818209838182099050838182099050838182099050838182099050838183099150508281830991508282860994508285850993508284850991508282860994508285850993508284860994508285850993508284860994508285860991508282860991508282830991508282850993508284850991508282830991508282860994508285850993508284850991508282850991508282860994508285850993508284860994508285850993508284850991508282830991508282850991508282860994508285860991508282860991508282850993508284860994508285850993508284860994508285850993508284850991508282850991508282830991508282860994508285850993508284850991508282850991508282830991508282860994508285860991508282830990508281820990508281830990508281860990508281820990508281820990508281820990508281820990508281830991508282850993508284860994508285850993508284860994508285860991508282860991508282830991508282830991508282830991508282860991508282850993508284850991508282850991508282830991508282860994508285860991508282860991508282850993508284860994508285860991508282830991508282850993508284860994508285860991508282850993508284860994508285850993508284850991508282850991508282860994508285850993508284850991508282850991508282830991508282830991508282860994508285860991508282830991508282830991508282860991508282850993508284860994508285860991508282860990508281820990508281820990508281830991508282850993508284850991508282860994508285850993508284860994508285850993508284860994508285850993508284850991508282850990508281850991508282830991508282830991508282820991505081818509935081848409925081838509935081848409925081838509935081848509905081818509905081818409925050808284099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808383099392505050565b82805482825590600052602060002090810192821561143d579160200282015b8281111561143d578251825591602001919060010190611422565b506114499291506114a6565b5090565b82805482825590600052602060002090810192821561149a579160200282015b8281111561149a578251805161148a918491602090910190611402565b509160200191906001019061146d565b506114499291506114c3565b6114c091905b8082111561144957600081556001016114ac565b90565b6114c091905b808211156114495760006114dd82826114e6565b506001016114c9565b508054600082559060005260206000209081019061150491906114a6565b5056fe30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47706f736974696f6e2049447320636f6e737472756374696f6e206661696c6564213fa265627a7a723058206097dad1ca89e3f16cbdb07809c67ec6fb5190a98caa2db6dcfa05eec0e49e8a64736f6c634300050a00326080604052620000387f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b036200007216565b6200006c7f4e2312e0000000000000000000000000000000000000000000000000000000006001600160e01b036200007216565b62000141565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200010457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152600360205260409020805460ff19166001179055565b612bb880620001516000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c8063a457c2d7116100c3578063d8c55af71161007c578063d8c55af71461056e578063dd62ed3e1461058b578063ddca3f43146105b9578063e03031a6146105c1578063f23a6e61146105de578063f55c79d01461067157610158565b8063a457c2d71461032c578063a9059cbb14610358578063b2016bd414610384578063bc197c811461038c578063d3c9727c146104d0578063d5f15a46146104f957610158565b80633950935111610115578063395093511461026257806340993b261461028e5780634343116a146102b75780635bd9e299146102da57806370a08231146102fe5780639003adfe1461032457610158565b806301ffc9a71461015d578063095ea7b314610198578063164e68de146101c457806316dbd776146101ec57806318160ddd1461022457806323b872dd1461022c575b600080fd5b6101846004803603602081101561017357600080fd5b50356001600160e01b031916610694565b604080519115158252519081900360200190f35b610184600480360360408110156101ae57600080fd5b506001600160a01b0381351690602001356106b3565b6101ea600480360360208110156101da57600080fd5b50356001600160a01b03166106ca565b005b6102126004803603602081101561020257600080fd5b50356001600160a01b0316610838565b60408051918252519081900360200190f35b61021261088c565b6101846004803603606081101561024257600080fd5b506001600160a01b03813581169160208101359091169060400135610892565b6101846004803603604081101561027857600080fd5b506001600160a01b0381351690602001356108e9565b6101ea600480360360608110156102a457600080fd5b5080359060208101359060400135610925565b610212600480360360408110156102cd57600080fd5b5080359060200135610c8b565b6102e2610e62565b604080516001600160a01b039092168252519081900360200190f35b6102126004803603602081101561031457600080fd5b50356001600160a01b0316610e71565b610212610e8c565b6101846004803603604081101561034257600080fd5b506001600160a01b038135169060200135610eaa565b6101846004803603604081101561036e57600080fd5b506001600160a01b038135169060200135610ee6565b6102e2610ef3565b6104b3600480360360a08110156103a257600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156103d557600080fd5b8201836020820111156103e757600080fd5b803590602001918460208302840111600160201b8311171561040857600080fd5b919390929091602081019035600160201b81111561042557600080fd5b82018360208201111561043757600080fd5b803590602001918460208302840111600160201b8311171561045857600080fd5b919390929091602081019035600160201b81111561047557600080fd5b82018360208201111561048757600080fd5b803590602001918460018302840111600160201b831117156104a857600080fd5b509092509050610f02565b604080516001600160e01b03199092168252519081900360200190f35b6101ea600480360360608110156104e657600080fd5b5080359060208101359060400135610f46565b6101ea6004803603604081101561050f57600080fd5b81359190810190604081016020820135600160201b81111561053057600080fd5b82018360208201111561054257600080fd5b803590602001918460208302840111600160201b8311171561056357600080fd5b5090925090506111e2565b6102126004803603602081101561058457600080fd5b5035611897565b610212600480360360408110156105a157600080fd5b506001600160a01b03813581169160200135166118b5565b6102126118e0565b6101ea600480360360208110156105d757600080fd5b50356118e6565b6104b3600480360360a08110156105f457600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135600160201b81111561063357600080fd5b82018360208201111561064557600080fd5b803590602001918460018302840111600160201b8311171561066657600080fd5b509092509050611c3e565b6102126004803603604081101561068757600080fd5b5080359060200135611c6d565b6001600160e01b03191660009081526003602052604090205460ff1690565b60006106c0338484611e0a565b5060015b92915050565b60006106d461088c565b6106ef6106e084610e71565b6008549063ffffffff611ef616565b816106f657fe5b6001600160a01b0384166000908152600c60205260408120549290910492509061072790839063ffffffff611f4f16565b90508015610833576001600160a01b0383166000908152600c60205260409020829055600d5461075d908263ffffffff611f9116565b600d556005546040805163a9059cbb60e01b81526001600160a01b038681166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156107b657600080fd5b505af11580156107ca573d6000803e3d6000fd5b505050506040513d60208110156107e057600080fd5b5051610833576040805162461bcd60e51b815260206004820152601a60248201527f7769746864726177616c207472616e73666572206661696c6564000000000000604482015290519081900360640190fd5b505050565b60008061084361088c565b61084f6106e085610e71565b8161085657fe5b6001600160a01b0385166000908152600c6020526040902054919004915061088590829063ffffffff611f4f16565b9392505050565b60025490565b600061089f848484611feb565b6001600160a01b0384166000908152600160209081526040808320338085529252909120546108df9186916108da908663ffffffff611f4f16565b611e0a565b5060019392505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916106c09185906108da908663ffffffff611f9116565b60006109318484611c6d565b905081811015610988576040805162461bcd60e51b815260206004820152601e60248201527f6d696e696d756d2062757920616d6f756e74206e6f7420726561636865640000604482015290519081900360640190fd5b600554604080516323b872dd60e01b81523360048201523060248201526044810187905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b1580156109e257600080fd5b505af11580156109f6573d6000803e3d6000fd5b505050506040513d6020811015610a0c57600080fd5b5051610a56576040805162461bcd60e51b815260206004820152601460248201527318dbdcdd081d1c985b9cd9995c8819985a5b195960621b604482015290519081900360640190fd5b6000670de0b6b3a7640000610a7660075487611ef690919063ffffffff16565b81610a7d57fe5b049050610a9581600854611f9190919063ffffffff16565b6008556000610aaa868363ffffffff611f4f16565b600554600480546040805163095ea7b360e01b81526001600160a01b039283169381019390935260248301859052519394509091169163095ea7b3916044808201926020929091908290030181600087803b158015610b0857600080fd5b505af1158015610b1c573d6000803e3d6000fd5b505050506040513d6020811015610b3257600080fd5b5051610b85576040805162461bcd60e51b815260206004820152601a60248201527f617070726f76616c20666f722073706c697473206661696c6564000000000000604482015290519081900360640190fd5b610b8e81612138565b600454600b80546001600160a01b039092169163f242432a9130913391908a908110610bb657fe5b6000918252602082200154604080516001600160e01b031960e088901b1681526001600160a01b03958616600482015293909416602484015260448301526064820188905260a0608483015260a48201819052915160e4808301939282900301818387803b158015610c2757600080fd5b505af1158015610c3b573d6000803e3d6000fd5b5050604080518981526020810186905280820187905290518893503392507f4f62630f51608fc8a7603a9391a5101e58bd7c276139366fc107dc3b67c3dcf89181900360600190a3505050505050565b600b546000908210610cdc576040805162461bcd60e51b81526020600482015260156024820152740d2dcecc2d8d2c840deeae8c6dedaca40d2dcc8caf605b1b604482015290519081900360640190fd5b6060610ce66122c7565b90506000610d07600754670de0b6b3a7640000611f4f90919063ffffffff16565b610d1f86670de0b6b3a764000063ffffffff611ef616565b81610d2657fe5b0490506000828581518110610d3757fe5b602002602001015190506000610d5e670de0b6b3a764000083611ef690919063ffffffff16565b905060005b8451811015610dc957868114610dc1576000858281518110610d8157fe5b60200260200101519050610dbd610da18683611f4f90919063ffffffff16565b610db1858463ffffffff611ef616565b9063ffffffff61249616565b9250505b600101610d63565b5060008111610e1f576040805162461bcd60e51b815260206004820152601b60248201527f6d7573742068617665206e6f6e2d7a65726f2062616c616e6365730000000000604482015290519081900360640190fd5b610e5782610e4b610e3e84670de0b6b3a764000063ffffffff61249616565b869063ffffffff611f9116565b9063ffffffff611f4f16565b979650505050505050565b6004546001600160a01b031681565b6001600160a01b031660009081526020819052604090205490565b6000610ea5600d54600854611f4f90919063ffffffff16565b905090565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916106c09185906108da908663ffffffff611f4f16565b60006106c0338484611feb565b6005546001600160a01b031681565b60006001600160a01b03891630148015610f2357506001600160a01b038816155b15610f36575063bc197c8160e01b610f3a565b5060005b98975050505050505050565b6000610f528484610c8b565b905081811115610fa9576040805162461bcd60e51b815260206004820152601c60248201527f6d6178696d756d2073656c6c20616d6f756e7420657863656564656400000000604482015290519081900360640190fd5b600454600b80546001600160a01b039092169163f242432a91339130919088908110610fd157fe5b6000918252602082200154604080516001600160e01b031960e088901b1681526001600160a01b03958616600482015293909416602484015260448301526064820186905260a0608483015260a48201819052915160e4808301939282900301818387803b15801561104257600080fd5b505af1158015611056573d6000803e3d6000fd5b505050506000611079600754670de0b6b3a7640000611f4f90919063ffffffff16565b60075461108d90879063ffffffff611ef616565b8161109457fe5b0490506110ac81600854611f9190919063ffffffff16565b60085560006110c1868363ffffffff611f9116565b90506110cc816124c6565b6005546040805163a9059cbb60e01b81523360048201526024810189905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b15801561112057600080fd5b505af1158015611134573d6000803e3d6000fd5b505050506040513d602081101561114a57600080fd5b5051611196576040805162461bcd60e51b81526020600482015260166024820152751c995d1d5c9b881d1c985b9cd9995c8819985a5b195960521b604482015290519081900360640190fd5b60408051878152602081018490528082018590529051869133917fadcf2a240ed9300d681d9a3f5382b6c1beed1b7e46643e0c7b42cbe6e2d766b49181900360600190a3505050505050565b60008311611237576040805162461bcd60e51b815260206004820152601860248201527f66756e64696e67206d757374206265206e6f6e2d7a65726f0000000000000000604482015290519081900360640190fd5b600b546040805182815260208084028201019091526060918015611265578160200160208202803883390190505b509050600061127261088c565b9050600081156113925783156112b95760405162461bcd60e51b8152600401808060200182810382526032815260200180612ac76032913960400191505060405180910390fd5b60606112c36122c7565b90506000805b82518110156112ff5760008382815181106112e057fe5b60200260200101519050808310156112f6578092505b506001016112c9565b5060005b825181101561136f5760008261133585848151811061131e57fe5b60200260200101518c611ef690919063ffffffff16565b8161133c57fe5b04905061134f8a8263ffffffff611f4f16565b87838151811061135b57fe5b602090810291909101015250600101611303565b5080611381898663ffffffff611ef616565b8161138857fe5b04925050506114e1565b83156114de57600b5484146113e0576040805162461bcd60e51b815260206004820152600f60248201526e3434b73a103632b733ba341037b33360891b604482015290519081900360640190fd5b6000805b858110156114185760008787838181106113fa57fe5b9050602002013590508083101561140f578092505b506001016113e4565b5060005b858110156114db5760008261144c89898581811061143657fe5b905060200201358b611ef690919063ffffffff16565b8161145357fe5b049050600081116114ab576040805162461bcd60e51b815260206004820152601e60248201527f6d7573742068696e7420612076616c696420646973747269627574696f6e0000604482015290519081900360640190fd5b6114bb898263ffffffff611f4f16565b8683815181106114c757fe5b60209081029190910101525060010161141c565b50505b50845b600554604080516323b872dd60e01b81523360048201523060248201526044810189905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b15801561153b57600080fd5b505af115801561154f573d6000803e3d6000fd5b505050506040513d602081101561156557600080fd5b50516115b8576040805162461bcd60e51b815260206004820152601760248201527f66756e64696e67207472616e73666572206661696c6564000000000000000000604482015290519081900360640190fd5b600554600480546040805163095ea7b360e01b81526001600160a01b0392831693810193909352602483018a90525192169163095ea7b3916044808201926020929091908290030181600087803b15801561161257600080fd5b505af1158015611626573d6000803e3d6000fd5b505050506040513d602081101561163c57600080fd5b505161168f576040805162461bcd60e51b815260206004820152601a60248201527f617070726f76616c20666f722073706c697473206661696c6564000000000000604482015290519081900360640190fd5b61169886612138565b6116a2338261263d565b60048054604051631759616b60e11b815230928101838152336024830181905260a060448401908152600b805460a486018190526001600160a01b0390961696632eb2c2d6969095939491938b93916064820191608481019160c4909101908790801561172e57602002820191906000526020600020905b81548152602001906001019080831161171a575b50508481038352855181528551602091820191808801910280838360005b8381101561176457818101518382015260200161174c565b50505050905001848103825260008152602001602001975050505050505050600060405180830381600087803b15801561179d57600080fd5b505af11580156117b1573d6000803e3d6000fd5b506000925050505b8351811015611807576117e88482815181106117d157fe5b602002602001015188611f4f90919063ffffffff16565b8482815181106117f457fe5b60209081029190910101526001016117b9565b50336001600160a01b03167fec2dc3e5a3bb9aa0a1deb905d2bd23640d07f107e6ceb484024501aad964a95184836040518080602001838152602001828103825284818151815260200191508051906020019060200280838360005b8381101561187b578181015183820152602001611863565b50505050905001935050505060405180910390a2505050505050565b600681815481106118a457fe5b600091825260209091200154905081565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60075481565b60606118f06122c7565b90506060815160405190808252806020026020018201604052801561191f578160200160208202803883390190505b509050600061192c61088c565b905060005b835181101561198857816119618686848151811061194b57fe5b6020026020010151611ef690919063ffffffff16565b8161196857fe5b0483828151811061197557fe5b6020908102919091010152600101611931565b50600554604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156119d457600080fd5b505afa1580156119e8573d6000803e3d6000fd5b505050506040513d60208110156119fe57600080fd5b50519050611a0c3386612739565b600554604080516370a0823160e01b81523060048201529051611a91926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611a5857600080fd5b505afa158015611a6c573d6000803e3d6000fd5b505050506040513d6020811015611a8257600080fd5b5051829063ffffffff611f4f16565b60048054604051631759616b60e11b815230928101838152336024830181905260a060448401908152600b805460a486018190529798506001600160a01b0390951696632eb2c2d69695929492938b939092916064820191608481019160c49091019087908015611b2157602002820191906000526020600020905b815481526020019060010190808311611b0d575b50508481038352855181528551602091820191808801910280838360005b83811015611b57578181015183820152602001611b3f565b50505050905001848103825260008152602001602001975050505050505050600060405180830381600087803b158015611b9057600080fd5b505af1158015611ba4573d6000803e3d6000fd5b50505050336001600160a01b03167f8b4b2c8ebd04c47fc8bce136a85df9b93fcb1f47c8aa296457d4391519d190e78483886040518080602001848152602001838152602001828103825285818151815260200191508051906020019060200280838360005b83811015611c22578181015183820152602001611c0a565b5050505090500194505050505060405180910390a25050505050565b60006001600160a01b038716301415611c5f575063f23a6e6160e01b611c63565b5060005b9695505050505050565b600b546000908210611cbe576040805162461bcd60e51b81526020600482015260156024820152740d2dcecc2d8d2c840deeae8c6dedaca40d2dcc8caf605b1b604482015290519081900360640190fd5b6060611cc86122c7565b90506000611d03670de0b6b3a7640000611ced60075488611ef690919063ffffffff16565b81611cf457fe5b8791900463ffffffff611f4f16565b90506000828581518110611d1357fe5b602002602001015190506000611d3a670de0b6b3a764000083611ef690919063ffffffff16565b905060005b8451811015611d8957868114611d81576000858281518110611d5d57fe5b60200260200101519050611d7d610da18683611f9190919063ffffffff16565b9250505b600101611d3f565b5060008111611ddf576040805162461bcd60e51b815260206004820152601b60248201527f6d7573742068617665206e6f6e2d7a65726f2062616c616e6365730000000000604482015290519081900360640190fd5b610e57611dfa82670de0b6b3a764000063ffffffff61249616565b610e4b848663ffffffff611f9116565b6001600160a01b038316611e4f5760405162461bcd60e51b8152600401808060200182810382526024815260200180612b606024913960400191505060405180910390fd5b6001600160a01b038216611e945760405162461bcd60e51b8152600401808060200182810382526022815260200180612aa56022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600082611f05575060006106c4565b82820282848281611f1257fe5b04146108855760405162461bcd60e51b8152600401808060200182810382526021815260200180612af96021913960400191505060405180910390fd5b600061088583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612827565b600082820183811015610885576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b0383166120305760405162461bcd60e51b8152600401808060200182810382526025815260200180612b3b6025913960400191505060405180910390fd5b6001600160a01b0382166120755760405162461bcd60e51b8152600401808060200182810382526023815260200180612a826023913960400191505060405180910390fd5b6120808383836128be565b6001600160a01b0383166000908152602081905260409020546120a9908263ffffffff611f4f16565b6001600160a01b0380851660009081526020819052604080822093909355908416815220546120de908263ffffffff611f9116565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600654600019015b600081126122c357606061216a6009838154811061215a57fe5b9060005260206000200154612a1d565b905060005b600a838154811061217c57fe5b6000918252602090912001548110156122b857600454600554600a80546001600160a01b03938416936372ce427593169190879081106121b857fe5b9060005260206000200184815481106121cd57fe5b9060005260206000200154600687815481106121e557fe5b906000526020600020015486896040518663ffffffff1660e01b815260040180866001600160a01b03166001600160a01b0316815260200185815260200184815260200180602001838152602001828103825284818151815260200191508051906020019060200280838360005b8381101561226b578181015183820152602001612253565b505050509050019650505050505050600060405180830381600087803b15801561229457600080fd5b505af11580156122a8573d6000803e3d6000fd5b50506001909201915061216f9050565b505060001901612140565b5050565b606080600b805490506040519080825280602002602001820160405280156122f9578160200160208202803883390190505b50905060005b600b54811015612336573082828151811061231657fe5b6001600160a01b03909216602092830291909101909101526001016122ff565b5060048054604080516313849cfd60e21b81529283019081528351604484015283516001600160a01b0390921692634e1273f4928592600b929091829160248101916064909101906020808801910280838360005b838110156123a357818101518382015260200161238b565b5050505090500183810382528481815481526020019150805480156123e757602002820191906000526020600020905b8154815260200190600101908083116123d3575b505094505050505060006040518083038186803b15801561240757600080fd5b505afa15801561241b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561244457600080fd5b810190808051600160201b81111561245b57600080fd5b8201602081018481111561246e57600080fd5b81518560208202830111600160201b8211171561248a57600080fd5b50909550505050505090565b600082156124b5578160018403816124aa57fe5b0460010190506106c4565b8183816124be57fe5b049392505050565b60005b6006548110156122c35760606124e56009838154811061215a57fe5b905060005b600a83815481106124f757fe5b60009182526020909120015481101561263357600454600554600a80546001600160a01b0393841693639e7212ad931691908790811061253357fe5b90600052602060002001848154811061254857fe5b90600052602060002001546006878154811061256057fe5b906000526020600020015486896040518663ffffffff1660e01b815260040180866001600160a01b03166001600160a01b0316815260200185815260200184815260200180602001838152602001828103825284818151815260200191508051906020019060200280838360005b838110156125e65781810151838201526020016125ce565b505050509050019650505050505050600060405180830381600087803b15801561260f57600080fd5b505af1158015612623573d6000803e3d6000fd5b5050600190920191506124ea9050565b50506001016124c9565b6001600160a01b038216612698576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6126a4600083836128be565b6002546126b7908263ffffffff611f9116565b6002556001600160a01b0382166000908152602081905260409020546126e3908263ffffffff611f9116565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b03821661277e5760405162461bcd60e51b8152600401808060200182810382526021815260200180612b1a6021913960400191505060405180910390fd5b61278a826000836128be565b6001600160a01b0382166000908152602081905260409020546127b3908263ffffffff611f4f16565b6001600160a01b0383166000908152602081905260409020556002546127df908263ffffffff611f4f16565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600081848411156128b65760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561287b578181015183820152602001612863565b50505050905090810190601f1680156128a85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038316156128d6576128d6836106ca565b60006128e061088c565b90506000811561290c5760085482906128ff908563ffffffff611ef616565b8161290657fe5b0461290e565b825b90506001600160a01b0385161561297c576001600160a01b0385166000908152600c6020526040902054612948908263ffffffff611f4f16565b6001600160a01b0386166000908152600c6020526040902055600d54612974908263ffffffff611f4f16565b600d55612993565b60085461298f908263ffffffff611f9116565b6008555b6001600160a01b038416156129ff576001600160a01b0384166000908152600c60205260409020546129cb908263ffffffff611f9116565b6001600160a01b0385166000908152600c6020526040902055600d546129f7908263ffffffff611f9116565b600d55612a16565b600854612a12908263ffffffff611f4f16565b6008555b5050505050565b606081604051908082528060200260200182016040528015612a49578160200160208202803883390190505b50905060005b82811015612a7b57806001901b828281518110612a6857fe5b6020908102919091010152600101612a4f565b5091905056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737363616e6e6f742075736520646973747269627574696f6e2068696e7420616674657220696e697469616c2066756e64696e67536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f2061646472657373a265627a7a72305820dee06b86eb16c66ed2e2b2e95ce838ea52bedd448841735c32681061e0eaad7a64736f6c634300050a0032

Deployed ByteCode Sourcemap

88461:3610:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;88461:3610:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88856:51;;;:::i;:::-;;;;-1:-1:-1;;;;;88856:51:0;;;;;;;;;;;;;;91237:831;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;91237:831:0;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;91237:831:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;91237:831:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;91237:831:0;;-1:-1:-1;91237:831:0;-1:-1:-1;91237:831:0;;:::i;89016:1420::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;89016:1420:0;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;89016:1420:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;89016:1420:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;89016:1420:0;;-1:-1:-1;89016:1420:0;-1:-1:-1;89016:1420:0;:::i;:::-;;88856:51;;;-1:-1:-1;;;;;88856:51:0;;:::o;91237:831::-;91459:23;91500:47;91588:192;91608:20;;;;;;;;;-1:-1:-1;;;;;91608:20:0;91660:17;91696:15;91730:12;;91761:3;91631:148;;;;;;-1:-1:-1;;;;;91631:148:0;-1:-1:-1;;;;;91631:148:0;;;;;;-1:-1:-1;;;;;91631:148:0;-1:-1:-1;;;;;91631:148:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;91631:148:0;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;91631:148:0;;;91588:11;:192::i;:::-;91500:291;;91948:15;-1:-1:-1;;;;;91807:212:0;91916:17;-1:-1:-1;;;;;91807:212:0;91853:10;-1:-1:-1;;;;;91807:212:0;;91878:23;91978:12;;92005:3;91807:212;;;;-1:-1:-1;;;;;91807:212:0;-1:-1:-1;;;;;91807:212:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;;74:27;91807:212:0;;137:4:-1;117:14;;;-1:-1;;113:30;157:16;;;91807:212:0;;;;-1:-1:-1;91807:212:0;;-1:-1:-1;;;;;;91807:212:0;92037:23;91237:831;-1:-1:-1;;;;;;91237:831:0:o;89016:1420::-;89102:36;89153:23;89191:30;89236:9;89270:8;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;89259:66:0;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;89259:66:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;89259:66:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;89259:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;-1:-1;89338:20:0;89259:66;89338:42;;;;:49;;-1:-1:-1;;89338:49:0;;;89383:4;89338:49;;;;;;-1:-1:-1;;;89398:167:0;;;;:174;;;;;;;;;89585:17;:38;;-1:-1:-1;;;;;89585:38:0;;;-1:-1:-1;;;;;;89585:38:0;;;;;;;89634:15;:34;;;;;;;;;;;;;;;89679:28;;89087:238;;-1:-1:-1;89087:238:0;;-1:-1:-1;89259:66:0;;-1:-1:-1;;89259:66:0;;;-1:-1:-1;89679:28:0;;:12;;:28;;;-1:-1:-1;89679:28:0;-1:-1:-1;89679:28:0;;-1:-1:-1;;89679:28:0:i;:::-;-1:-1:-1;89718:3:0;:10;;;89814:12;:19;89803:31;;;;;;;;;;;;;;;;89771:1;;89803:31;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;89803:31:0;-1:-1:-1;89783:51:0;;;;:17;;:51;;;;;;:::i;:::-;-1:-1:-1;89850:6:0;89845:263;89866:12;:19;89862:23;;89845:263;;;89931:17;;89969:12;:15;;89907:21;;-1:-1:-1;;;;;89931:17:0;;:37;;89982:1;;89969:15;;;;;;;;;;;;;;89931:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;89931:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;89931:54:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;89931:54:0;90057:17;:20;;90000:42;;;;89931:54;;-1:-1:-1;89931:54:0;;90075:1;;90057:20;;;;;;;;;;;;;;;:39;-1:-1:-1;89887:3:0;;89845:263;;;;90151:1;90126:22;:26;90118:63;;;;;-1:-1:-1;;;90118:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;90226:12;:19;90210:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;90194:52:0;;;;:13;;:52;;;;;;:::i;:::-;-1:-1:-1;90294:12:0;:19;90257:69;;90323:1;90257:36;:69::i;:::-;90345:11;:18;:44;;90337:91;;;;-1:-1:-1;;;90337:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89016:1420;;;;;;;:::o;87165:1194::-;87243:14;87270:24;87348:8;87297:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;87297:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;87297:60:0;;;-1:-1:-1;;26:21;;;22:32;;6:49;;87297:60:0;;;49:4:-1;25:18;;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;87399:18:0;;87389:34;;87420:2;87399:23;;87389:34;;;;;;;;;;;;;;;;;;87297:60;-1:-1:-1;87368:18:0;;-1:-1:-1;87389:34:0;;-1:-1:-1;87399:23:0;-1:-1:-1;87389:34:0;;;;;;;21:6:-1;;104:10;87389:34:0;87::-1;135:17;;-1:-1;87389:34:0;-1:-1:-1;87510:66:0;87486:4;87475:16;;87468:109;-1:-1:-1;;;87637:7:0;87633:42;;87609:4;87598:16;;87591:85;87732:66;87708:4;87697:16;;87690:109;87855:41;;87831:4;87820:16;;87813:84;-1:-1:-1;;;87929:3:0;87918:15;;87911:108;87475:16;-1:-1:-1;;88050:102:0;88070:11;:18;88066:1;:22;88050:102;;;88126:11;88138:1;88126:14;;;;;;;;;;;;;;;;88110:5;88121:1;88116:2;:6;88110:13;;;;;;;;;;;:30;-1:-1:-1;;;;;88110:30:0;;;;;;;;-1:-1:-1;88090:3:0;;88050:102;;;;88203:5;88197:12;88244:4;88237:5;88233:16;88287:3;88281:4;88278:1;88271:20;88261:30;-1:-1:-1;;;;;;;;88330:20:0;;88322:29;;;;;;87165:1194;;;;;;:::o;90444:785::-;90561:19;90558:150;;90638:15;;90597:11;;90614:60;;-1:-1:-1;;;;;90638:15:0;90655:18;90614:23;:60::i;:::-;27:10:-1;;39:1;23:18;;45:23;;-1:-1;90597:78:0;;;;;;;;;;;90690:7;;90558:150;90720:16;;;;;;;;90749:21;90773:17;90791:14;90773:33;;;;;;;;;;;;;;;;90749:57;;90819:13;90833:14;90819:29;;;;;;;;;;;;;;;;;;;27:10:-1;;39:1;23:18;;45:23;;90819:54:0;;;;;;;;;;90884:338;90904:16;90900:1;:20;90884:338;;;90942:268;90997:14;91030:165;91078:18;91119:12;91132:14;91119:28;;;;;;;;;;;;;;;;91175:1;91170;:6;;91030:25;:165::i;:::-;90942:36;:268::i;:::-;90922:3;;90884:338;;;;90444:785;;;;:::o;36090:188::-;36221:47;;;;;;;;-1:-1:-1;;36221:47:0;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;36221:47:0;;;;;;36211:58;;;;;;36090:188::o;34518:1253::-;34675:39;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;34675:39:0;;;;;;;34665:50;;;;;34630:7;;34744:3;34738:9;;;:14;;34630:7;;34799:177;-1:-1:-1;;;;;;;;;;;34833:1:0;34829:2;34822:16;34817:21;-1:-1:-1;;;;;;;;;;;;18320:1:0;-1:-1:-1;;;;;;;;;;;18218:77:0;34887:2;34883;34876:17;34872:2;34865:32;34858:46;34853:51;;34924:8;34929:2;34924:4;:8::i;:::-;34919:13;-1:-1:-1;34972:2:0;-1:-1:-1;;;;;;;;;;;34962:2:0;34958;34951:17;:23;;34799:177;;34989:3;:18;;;;-1:-1:-1;35001:1:0;34996:2;:6;:11;34989:18;:41;;;;35012:3;35011:4;:19;;;;-1:-1:-1;35024:1:0;35019:2;:6;35029:1;35019:11;35011:19;34986:70;;;35054:2;-1:-1:-1;;;;;;;;;;;35050:6:0;35045:11;;34986:70;35084:18;35117:7;;35114:563;;35153:3;35147:9;;;:14;;;-1:-1:-1;;;;;;35181:14:0;-1:-1:-1;;;;;;;;;;;18320:1:0;-1:-1:-1;;;;;;;;;;;18218:77:0;35244:2;35240;35233:17;35229:2;35222:32;35215:46;35210:51;;35276:7;35286:8;35291:2;35286:4;:8::i;:::-;35276:18;;35312:3;:18;;;;-1:-1:-1;35324:1:0;35319:2;:6;:11;35312:18;:41;;;;35335:3;35334:4;:19;;;;-1:-1:-1;35347:1:0;35342:2;:6;35352:1;35342:11;35334:19;35309:74;;;-1:-1:-1;;;;;;;;;;;35377:6:0;35309:74;35427:2;-1:-1:-1;;;;;;;;;;;35417:2:0;35413;35406:17;:23;35398:64;;;;;-1:-1:-1;;;35398:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;35480:12;35494:16;35522:1;-1:-1:-1;;;;;35514:21:0;35547:2;35551;35555;35559;35536:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;35536:26:0;;;35514:49;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;35514:49:0;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;35479:84:0;;;;35586:7;35578:32;;;;;-1:-1:-1;;;35578:32:0;;;;;;;;;;;;-1:-1:-1;;;35578:32:0;;;;;;;;;;;;;;;35647:3;35636:29;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;35636:29:0;;;;;;;;;-1:-1:-1;35636:29:0;-1:-1:-1;;;;35114:563:0;35697:1;35692:2;:6;35702:1;35692:11;35689:43;;;-1:-1:-1;;;35718:14:0;;;;35689:43;-1:-1:-1;35760:2:0;;34518:1253;-1:-1:-1;;;;;;;34518:1253:0:o;18330:15737::-;18374:6;-1:-1:-1;;;;;;;;;;;18218:77:0;21450:1;;21440:15;21435:20;;21510:1;21507;21504;21497:15;21548:1;21545;21542;21535:15;21530:20;;21586:1;21583;21580;21573:15;21568:20;;21624:1;21621;21618;21611:15;21606:20;;21662:1;21659;21656;21649:15;21644:20;;21700:1;21697;21694;21687:15;21682:20;;21765:1;21762;21759;21752:15;21807:1;21804;21801;21794:15;21789:20;;21849:1;21846;21843;21836:15;21831:20;;21891:1;21888;21885;21878:15;21873:20;;21933:1;21930;21927;21920:15;21915:20;;21975:1;21972;21969;21962:15;21957:20;;22017:1;22014;22011;22004:15;21999:20;;22059:1;22056;22053;22046:15;22041:20;;22101:1;22098;22095;22088:15;22083:20;;22143:1;22140;22137;22130:15;22125:20;;22185:1;22182;22179;22172:15;22167:20;;22227:1;22224;22221;22214:15;22209:20;;22269:1;22266;22263;22256:15;22251:20;;22311:1;22308;22305;22298:15;22293:20;;22353:1;22350;22347;22340:15;22335:20;;22395:1;22392;22389;22382:15;22377:20;;22437:1;22434;22431;22424:15;22419:20;;22479:1;22476;22473;22466:15;22461:20;;22521:1;22518;22515;22508:15;22503:20;;22563:1;22560;22557;22550:15;22545:20;;22605:1;22602;22599;22592:15;22587:20;;22647:1;22644;22641;22634:15;22629:20;;22689:1;22686;22683;22676:15;22671:20;;22731:1;22728;22725;22718:15;22713:20;;22773:1;22770;22767;22760:15;22755:20;;22815:1;22812;22809;22802:15;22797:20;;22857:1;22854;22851;22844:15;22839:20;;22899:1;22896;22893;22886:15;22881:20;;22941:1;22938;22935;22928:15;22923:20;;22983:1;22980;22977;22970:15;22965:20;;23025:1;23022;23019;23012:15;23007:20;;23067:1;23064;23061;23054:15;23049:20;;23109:1;23106;23103;23096:15;23091:20;;23151:1;23148;23145;23138:15;23133:20;;23193:1;23190;23187;23180:15;23175:20;;23235:1;23232;23229;23222:15;23217:20;;23277:1;23274;23271;23264:15;23259:20;;23319:1;23316;23313;23306:15;23301:20;;23361:1;23358;23355;23348:15;23343:20;;23403:1;23400;23397;23390:15;23385:20;;23445:1;23442;23439;23432:15;23427:20;;23487:1;23484;23481;23474:15;23469:20;;23529:1;23526;23523;23516:15;23511:20;;23571:1;23568;23565;23558:15;23553:20;;23613:1;23610;23607;23600:15;23595:20;;23655:1;23652;23649;23642:15;23637:20;;23697:1;23694;23691;23684:15;23679:20;;23739:1;23736;23733;23726:15;23721:20;;23781:1;23778;23775;23768:15;23763:20;;23823:1;23820;23817;23810:15;23805:20;;23865:1;23862;23859;23852:15;23847:20;;23907:1;23904;23901;23894:15;23889:20;;23949:1;23946;23943;23936:15;23931:20;;23991:1;23988;23985;23978:15;23973:20;;24033:1;24030;24027;24020:15;24015:20;;24075:1;24072;24069;24062:15;24057:20;;24117:1;24114;24111;24104:15;24099:20;;24159:1;24156;24153;24146:15;24141:20;;24201:1;24198;24195;24188:15;24183:20;;24243:1;24240;24237;24230:15;24225:20;;24316:1;24313;24310;24303:15;24362:1;24359;24356;24349:15;24344:20;;24408:1;24405;24402;24395:15;24390:20;;24454:1;24451;24448;24441:15;24436:20;;24500:1;24497;24494;24487:15;24482:20;;24546:1;24543;24540;24533:15;24528:20;;24267:304;24611:1;24608;24605;24598:15;24593:20;;24653:1;24650;24647;24640:15;24635:20;;24695:1;24692;24689;24682:15;24677:20;;24737:1;24734;24731;24724:15;24719:20;;24779:1;24776;24773;24766:15;24761:20;;24821:1;24818;24815;24808:15;24803:20;;24863:1;24860;24857;24850:15;24845:20;;24905:1;24902;24899;24892:15;24887:20;;24947:1;24944;24941;24934:15;24929:20;;24989:1;24986;24983;24976:15;24971:20;;25031:1;25028;25025;25018:15;25013:20;;25073:1;25070;25067;25060:15;25055:20;;25115:1;25112;25109;25102:15;25097:20;;25157:1;25154;25151;25144:15;25139:20;;25199:1;25196;25193;25186:15;25181:20;;25241:1;25238;25235;25228:15;25223:20;;25283:1;25280;25277;25270:15;25265:20;;25325:1;25322;25319;25312:15;25307:20;;25367:1;25364;25361;25354:15;25349:20;;25409:1;25406;25403;25396:15;25391:20;;25451:1;25448;25445;25438:15;25433:20;;25493:1;25490;25487;25480:15;25475:20;;25535:1;25532;25529;25522:15;25517:20;;25577:1;25574;25571;25564:15;25559:20;;25619:1;25616;25613;25606:15;25601:20;;25661:1;25658;25655;25648:15;25643:20;;25703:1;25700;25697;25690:15;25685:20;;25745:1;25742;25739;25732:15;25727:20;;25787:1;25784;25781;25774:15;25769:20;;25829:1;25826;25823;25816:15;25811:20;;25871:1;25868;25865;25858:15;25853:20;;25913:1;25910;25907;25900:15;25895:20;;25955:1;25952;25949;25942:15;25937:20;;25997:1;25994;25991;25984:15;25979:20;;26039:1;26036;26033;26026:15;26021:20;;26081:1;26078;26075;26068:15;26063:20;;26123:1;26120;26117;26110:15;26105:20;;26165:1;26162;26159;26152:15;26147:20;;26207:1;26204;26201;26194:15;26189:20;;26249:1;26246;26243;26236:15;26231:20;;26291:1;26288;26285;26278:15;26273:20;;26333:1;26330;26327;26320:15;26315:20;;26375:1;26372;26369;26362:15;26357:20;;26417:1;26414;26411;26404:15;26399:20;;26459:1;26456;26453;26446:15;26441:20;;26501:1;26498;26495;26488:15;26483:20;;26543:1;26540;26537;26530:15;26525:20;;26585:1;26582;26579;26572:15;26567:20;;26627:1;26624;26621;26614:15;26609:20;;26669:1;26666;26663;26656:15;26651:20;;26711:1;26708;26705;26698:15;26693:20;;26753:1;26750;26747;26740:15;26735:20;;26795:1;26792;26789;26782:15;26777:20;;26837:1;26834;26831;26824:15;26819:20;;26879:1;26876;26873;26866:15;26861:20;;26921:1;26918;26915;26908:15;26903:20;;26963:1;26960;26957;26950:15;26945:20;;27005:1;27002;26999;26992:15;26987:20;;27047:1;27044;27041;27034:15;27029:20;;27089:1;27086;27083;27076:15;27071:20;;27131:1;27128;27125;27118:15;27113:20;;27173:1;27170;27167;27160:15;27155:20;;27215:1;27212;27209;27202:15;27197:20;;27257:1;27254;27251;27244:15;27239:20;;27299:1;27296;27293;27286:15;27281:20;;27341:1;27338;27335;27328:15;27323:20;;27383:1;27380;27377;27370:15;27365:20;;27425:1;27422;27419;27412:15;27407:20;;27467:1;27464;27461;27454:15;27449:20;;27509:1;27506;27503;27496:15;27491:20;;27551:1;27548;27545;27538:15;27533:20;;27593:1;27590;27587;27580:15;27575:20;;27635:1;27632;27629;27622:15;27617:20;;27677:1;27674;27671;27664:15;27659:20;;27719:1;27716;27713;27706:15;27701:20;;27761:1;27758;27755;27748:15;27743:20;;27803:1;27800;27797;27790:15;27785:20;;27845:1;27842;27839;27832:15;27827:20;;27887:1;27884;27881;27874:15;27869:20;;27929:1;27926;27923;27916:15;27911:20;;27971:1;27968;27965;27958:15;27953:20;;28013:1;28010;28007;28000:15;27995:20;;28055:1;28052;28049;28042:15;28037:20;;28097:1;28094;28091;28084:15;28079:20;;28139:1;28136;28133;28126:15;28121:20;;28181:1;28178;28175;28168:15;28163:20;;28223:1;28220;28217;28210:15;28205:20;;28265:1;28262;28259;28252:15;28247:20;;28307:1;28304;28301;28294:15;28289:20;;28349:1;28346;28343;28336:15;28331:20;;28391:1;28388;28385;28378:15;28373:20;;28433:1;28430;28427;28420:15;28415:20;;28475:1;28472;28469;28462:15;28457:20;;28517:1;28514;28511;28504:15;28499:20;;28559:1;28556;28553;28546:15;28541:20;;28601:1;28598;28595;28588:15;28583:20;;28643:1;28640;28637;28630:15;28625:20;;28685:1;28682;28679;28672:15;28667:20;;28727:1;28724;28721;28714:15;28709:20;;28769:1;28766;28763;28756:15;28751:20;;28811:1;28808;28805;28798:15;28793:20;;28853:1;28850;28847;28840:15;28835:20;;28895:1;28892;28889;28882:15;28877:20;;28937:1;28934;28931;28924:15;28919:20;;28979:1;28976;28973;28966:15;28961:20;;29021:1;29018;29015;29008:15;29003:20;;29063:1;29060;29057;29050:15;29045:20;;29105:1;29102;29099;29092:15;29087:20;;29147:1;29144;29141;29134:15;29129:20;;29189:1;29186;29183;29176:15;29171:20;;29231:1;29228;29225;29218:15;29213:20;;29273:1;29270;29267;29260:15;29255:20;;29315:1;29312;29309;29302:15;29297:20;;29357:1;29354;29351;29344:15;29339:20;;21720:7658;29414:1;29411;29408;29401:15;29396:20;;29452:1;29449;29446;29439:15;29434:20;;29490:1;29487;29484;29477:15;29472:20;;29528:1;29525;29522;29515:15;29510:20;;29566:1;29563;29560;29553:15;29548:20;;29604:1;29601;29598;29591:15;29586:20;;29642:1;29639;29636;29629:15;29624:20;;29680:1;29677;29674;29667:15;29662:20;;21469:8228;29729:1;29726;29723;29716:15;29711:20;;29763:1;29760;29757;29750:15;29745:20;;29797:1;29794;29791;29784:15;29779:20;;29831:1;29828;29825;29818:15;29813:20;;29865:1;29862;29859;29852:15;29847:20;;29899:1;29896;29893;29886:15;29881:20;;29933:1;29930;29927;29920:15;29915:20;;29967:1;29964;29961;29954:15;29949:20;;30001:1;29998;29995;29988:15;29983:20;;30035:1;30032;30029;30022:15;30017:20;;30069:1;30066;30063;30056:15;30051:20;;30103:1;30100;30097;30090:15;30085:20;;30137:1;30134;30131;30124:15;30119:20;;30171:1;30168;30165;30158:15;30153:20;;30205:1;30202;30199;30192:15;30187:20;;30239:1;30236;30233;30226:15;30221:20;;30273:1;30270;30267;30260:15;30255:20;;30307:1;30304;30301;30294:15;30289:20;;30341:1;30338;30335;30328:15;30323:20;;30375:1;30372;30369;30362:15;30357:20;;30409:1;30406;30403;30396:15;30391:20;;30443:1;30440;30437;30430:15;30425:20;;30477:1;30474;30471;30464:15;30459:20;;30511:1;30508;30505;30498:15;30493:20;;30545:1;30542;30539;30532:15;30527:20;;30579:1;30576;30573;30566:15;30561:20;;30613:1;30610;30607;30600:15;30595:20;;30647:1;30644;30641;30634:15;30629:20;;30681:1;30678;30675;30668:15;30663:20;;30715:1;30712;30709;30702:15;30697:20;;30749:1;30746;30743;30736:15;30731:20;;30783:1;30780;30777;30770:15;30765:20;;30817:1;30814;30811;30804:15;30799:20;;30851:1;30848;30845;30838:15;30833:20;;30885:1;30882;30879;30872:15;30867:20;;30919:1;30916;30913;30906:15;30901:20;;30953:1;30950;30947;30940:15;30935:20;;30987:1;30984;30981;30974:15;30969:20;;31021:1;31018;31015;31008:15;31003:20;;31055:1;31052;31049;31042:15;31037:20;;31089:1;31086;31083;31076:15;31071:20;;31123:1;31120;31117;31110:15;31105:20;;31157:1;31154;31151;31144:15;31139:20;;31191:1;31188;31185;31178:15;31173:20;;31225:1;31222;31219;31212:15;31207:20;;31259:1;31256;31253;31246:15;31241:20;;31293:1;31290;31287;31280:15;31275:20;;31327:1;31324;31321;31314:15;31309:20;;31361:1;31358;31355;31348:15;31343:20;;31395:1;31392;31389;31382:15;31377:20;;31429:1;31426;31423;31416:15;31411:20;;31463:1;31460;31457;31450:15;31445:20;;31497:1;31494;31491;31484:15;31479:20;;31531:1;31528;31525;31518:15;31513:20;;31565:1;31562;31559;31552:15;31547:20;;31599:1;31596;31593;31586:15;31581:20;;31633:1;31630;31627;31620:15;31615:20;;31667:1;31664;31661;31654:15;31649:20;;31701:1;31698;31695;31688:15;31683:20;;31735:1;31732;31729;31722:15;31717:20;;31769:1;31766;31763;31756:15;31751:20;;31803:1;31800;31797;31790:15;31785:20;;31837:1;31834;31831;31824:15;31819:20;;31871:1;31868;31865;31858:15;31853:20;;31905:1;31902;31899;31892:15;31887:20;;31939:1;31936;31933;31926:15;31921:20;;31973:1;31970;31967;31960:15;31955:20;;32007:1;32004;32001;31994:15;31989:20;;32041:1;32038;32035;32028:15;32023:20;;32075:1;32072;32069;32062:15;32057:20;;32109:1;32106;32103;32096:15;32091:20;;32143:1;32140;32137;32130:15;32125:20;;32177:1;32174;32171;32164:15;32159:20;;32211:1;32208;32205;32198:15;32193:20;;32245:1;32242;32239;32232:15;32227:20;;32279:1;32276;32273;32266:15;32261:20;;32313:1;32310;32307;32300:15;32295:20;;32347:1;32344;32341;32334:15;32329:20;;32381:1;32378;32375;32368:15;32363:20;;32415:1;32412;32409;32402:15;32397:20;;32449:1;32446;32443;32436:15;32431:20;;32483:1;32480;32477;32470:15;32465:20;;32517:1;32514;32511;32504:15;32499:20;;32551:1;32548;32545;32538:15;32533:20;;32585:1;32582;32579;32572:15;32567:20;;32619:1;32616;32613;32606:15;32601:20;;32653:1;32650;32647;32640:15;32635:20;;32687:1;32684;32681;32674:15;32669:20;;32721:1;32718;32715;32708:15;32703:20;;32755:1;32752;32749;32742:15;32737:20;;32789:1;32786;32783;32776:15;32771:20;;32823:1;32820;32817;32810:15;32805:20;;32857:1;32854;32851;32844:15;32839:20;;32891:1;32888;32885;32878:15;32873:20;;32925:1;32922;32919;32912:15;32907:20;;32959:1;32956;32953;32946:15;32941:20;;32993:1;32990;32987;32980:15;32975:20;;33027:1;33024;33021;33014:15;33009:20;;33061:1;33058;33055;33048:15;33043:20;;33095:1;33092;33089;33082:15;33077:20;;33129:1;33126;33123;33116:15;33111:20;;33163:1;33160;33157;33150:15;33145:20;;33197:1;33194;33191;33184:15;33179:20;;33231:1;33228;33225;33218:15;33213:20;;33265:1;33262;33259;33252:15;33247:20;;33299:1;33296;33293;33286:15;33281:20;;33333:1;33330;33327;33320:15;33315:20;;33367:1;33364;33361;33354:15;33349:20;;33401:1;33398;33395;33388:15;33383:20;;33435:1;33432;33429;33422:15;33417:20;;33469:1;33466;33463;33456:15;33451:20;;33503:1;33500;33497;33490:15;33485:20;;33537:1;33534;33531;33524:15;33519:20;;33571:1;33568;33565;33558:15;33553:20;;33605:1;33602;33599;33592:15;33587:20;;33639:1;33636;33633;33626:15;33621:20;;33673:1;33670;33667;33660:15;33655:20;;33707:1;33704;33701;33694:15;33689:20;;33741:1;33738;33735;33728:15;33723:20;;33775:1;33772;33769;33762:15;33757:20;;33809:1;33806;33803;33796:15;33791:20;;33843:1;33840;33837;33830:15;33825:20;;33877:1;33874;33871;33864:15;33859:20;;33911:1;33908;33905;33898:15;33893:20;;33945:1;33942;33939;33932:15;33927:20;;33979:1;33976;33973;33966:15;33961:20;;34013:1;34010;34007;34000:15;33995:20;;34047:1;34044;34041;34034:15;34029:20;18488:15572;-1:-1:-1;;;18488:15572:0:o;88461:3610::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;88461:3610:0;;;-1:-1:-1;88461:3610:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;88461:3610:0;;;-1:-1:-1;88461:3610:0;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o

Swarm Source

bzzr://dee06b86eb16c66ed2e2b2e95ce838ea52bedd448841735c32681061e0eaad7a
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.