APE Price: $1.52 (-4.72%)

Contract

0xf309982b384217595FE5d4dbDE701688Bdf0d459

Overview

APE Balance

Apechain LogoApechain LogoApechain Logo0 APE

APE Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Contract URI66373272024-12-13 21:08:0925 hrs ago1734124089IN
0xf309982b...8Bdf0d459
0 APE0.0024223625.42069

Parent Transaction Hash Block From To
View All Internal Transactions

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PrimapePrediction

Compiler Version
v0.8.26+commit.8a97fa7a

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at apescan.io on 2024-12-13
*/

// File: @thirdweb-dev/contracts/extension/interface/IOwnable.sol


pragma solidity ^0.8.0;

/// @author thirdweb

/**
 *  Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading
 *  who the 'owner' of the inheriting smart contract is, and lets the inheriting contract perform conditional logic that uses
 *  information about who the contract's owner is.
 */

interface IOwnable {
    /// @dev Returns the owner of the contract.
    function owner() external view returns (address);

    /// @dev Lets a module admin set a new owner for the contract. The new owner must be a module admin.
    function setOwner(address _newOwner) external;

    /// @dev Emitted when a new Owner is set.
    event OwnerUpdated(address indexed prevOwner, address indexed newOwner);
}

// File: @thirdweb-dev/contracts/extension/Ownable.sol


pragma solidity ^0.8.0;

/// @author thirdweb


/**
 *  @title   Ownable
 *  @notice  Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading
 *           who the 'owner' of the inheriting smart contract is, and lets the inheriting contract perform conditional logic that uses
 *           information about who the contract's owner is.
 */

abstract contract Ownable is IOwnable {
    /// @dev The sender is not authorized to perform the action
    error OwnableUnauthorized();

    /// @dev Owner of the contract (purpose: OpenSea compatibility)
    address private _owner;

    /// @dev Reverts if caller is not the owner.
    modifier onlyOwner() {
        if (msg.sender != _owner) {
            revert OwnableUnauthorized();
        }
        _;
    }

    /**
     *  @notice Returns the owner of the contract.
     */
    function owner() public view override returns (address) {
        return _owner;
    }

    /**
     *  @notice Lets an authorized wallet set a new owner for the contract.
     *  @param _newOwner The address to set as the new owner of the contract.
     */
    function setOwner(address _newOwner) external override {
        if (!_canSetOwner()) {
            revert OwnableUnauthorized();
        }
        _setupOwner(_newOwner);
    }

    /// @dev Lets a contract admin set a new owner for the contract. The new owner must be a contract admin.
    function _setupOwner(address _newOwner) internal {
        address _prevOwner = _owner;
        _owner = _newOwner;

        emit OwnerUpdated(_prevOwner, _newOwner);
    }

    /// @dev Returns whether owner can be set in the given execution context.
    function _canSetOwner() internal view virtual returns (bool);
}

// File: @thirdweb-dev/contracts/extension/interface/IPermissions.sol


pragma solidity ^0.8.0;

/// @author thirdweb

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IPermissions {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

// File: @thirdweb-dev/contracts/lib/Strings.sol


pragma solidity ^0.8.0;

/// @author thirdweb

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte,
    /// and the alphabets are capitalized conditionally according to
    /// https://eips.ethereum.org/EIPS/eip-55
    function toHexStringChecksummed(address value) internal pure returns (string memory str) {
        str = toHexString(value);
        /// @solidity memory-safe-assembly
        assembly {
            let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...`
            let o := add(str, 0x22)
            let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... `
            let t := shl(240, 136) // `0b10001000 << 240`
            for {
                let i := 0
            } 1 {

            } {
                mstore(add(i, i), mul(t, byte(i, hashed)))
                i := add(i, 1)
                if eq(i, 20) {
                    break
                }
            }
            mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask)))))
            o := add(o, 0x20)
            mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask)))))
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
    function toHexString(address value) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is encoded using 2 hexadecimal digits per byte.
    function toHexStringNoPrefix(address value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            str := mload(0x40)

            // Allocate the memory.
            // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
            // 0x02 bytes for the prefix, and 0x28 bytes for the digits.
            // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80.
            mstore(0x40, add(str, 0x80))

            // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            str := add(str, 2)
            mstore(str, 40)

            let o := add(str, 0x20)
            mstore(add(o, 40), 0)

            value := shl(96, value)

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            for {
                let i := 0
            } 1 {

            } {
                let p := add(o, add(i, i))
                let temp := byte(i, value)
                mstore8(add(p, 1), mload(and(temp, 15)))
                mstore8(p, mload(shr(4, temp)))
                i := add(i, 1)
                if eq(i, 20) {
                    break
                }
            }
        }
    }

    /// @dev Returns the hex encoded string from the raw bytes.
    /// The output is encoded using 2 hexadecimal digits per byte.
    function toHexString(bytes memory raw) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(raw);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hex encoded string from the raw bytes.
    /// The output is encoded using 2 hexadecimal digits per byte.
    function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            let length := mload(raw)
            str := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix.
            mstore(str, add(length, length)) // Store the length of the output.

            // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            let o := add(str, 0x20)
            let end := add(raw, length)

            for {

            } iszero(eq(raw, end)) {

            } {
                raw := add(raw, 1)
                mstore8(add(o, 1), mload(and(mload(raw), 15)))
                mstore8(o, mload(and(shr(4, mload(raw)), 15)))
                o := add(o, 2)
            }
            mstore(o, 0) // Zeroize the slot after the string.
            mstore(0x40, add(o, 0x20)) // Allocate the memory.
        }
    }
}

// File: @thirdweb-dev/contracts/extension/Permissions.sol


pragma solidity ^0.8.0;

/// @author thirdweb



/**
 *  @title   Permissions
 *  @dev     This contracts provides extending-contracts with role-based access control mechanisms
 */
contract Permissions is IPermissions {
    /// @dev The `account` is missing a role.
    error PermissionsUnauthorizedAccount(address account, bytes32 neededRole);

    /// @dev The `account` already is a holder of `role`
    error PermissionsAlreadyGranted(address account, bytes32 role);

    /// @dev Invalid priviledge to revoke
    error PermissionsInvalidPermission(address expected, address actual);

    /// @dev Map from keccak256 hash of a role => a map from address => whether address has role.
    mapping(bytes32 => mapping(address => bool)) private _hasRole;

    /// @dev Map from keccak256 hash of a role to role admin. See {getRoleAdmin}.
    mapping(bytes32 => bytes32) private _getRoleAdmin;

    /// @dev Default admin role for all roles. Only accounts with this role can grant/revoke other roles.
    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /// @dev Modifier that checks if an account has the specified role; reverts otherwise.
    modifier onlyRole(bytes32 role) {
        _checkRole(role, msg.sender);
        _;
    }

    /**
     *  @notice         Checks whether an account has a particular role.
     *  @dev            Returns `true` if `account` has been granted `role`.
     *
     *  @param role     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     *  @param account  Address of the account for which the role is being checked.
     */
    function hasRole(bytes32 role, address account) public view override returns (bool) {
        return _hasRole[role][account];
    }

    /**
     *  @notice         Checks whether an account has a particular role;
     *                  role restrictions can be swtiched on and off.
     *
     *  @dev            Returns `true` if `account` has been granted `role`.
     *                  Role restrictions can be swtiched on and off:
     *                      - If address(0) has ROLE, then the ROLE restrictions
     *                        don't apply.
     *                      - If address(0) does not have ROLE, then the ROLE
     *                        restrictions will apply.
     *
     *  @param role     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     *  @param account  Address of the account for which the role is being checked.
     */
    function hasRoleWithSwitch(bytes32 role, address account) public view returns (bool) {
        if (!_hasRole[role][address(0)]) {
            return _hasRole[role][account];
        }

        return true;
    }

    /**
     *  @notice         Returns the admin role that controls the specified role.
     *  @dev            See {grantRole} and {revokeRole}.
     *                  To change a role's admin, use {_setRoleAdmin}.
     *
     *  @param role     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     */
    function getRoleAdmin(bytes32 role) external view override returns (bytes32) {
        return _getRoleAdmin[role];
    }

    /**
     *  @notice         Grants a role to an account, if not previously granted.
     *  @dev            Caller must have admin role for the `role`.
     *                  Emits {RoleGranted Event}.
     *
     *  @param role     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     *  @param account  Address of the account to which the role is being granted.
     */
    function grantRole(bytes32 role, address account) public virtual override {
        _checkRole(_getRoleAdmin[role], msg.sender);
        if (_hasRole[role][account]) {
            revert PermissionsAlreadyGranted(account, role);
        }
        _setupRole(role, account);
    }

    /**
     *  @notice         Revokes role from an account.
     *  @dev            Caller must have admin role for the `role`.
     *                  Emits {RoleRevoked Event}.
     *
     *  @param role     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     *  @param account  Address of the account from which the role is being revoked.
     */
    function revokeRole(bytes32 role, address account) public virtual override {
        _checkRole(_getRoleAdmin[role], msg.sender);
        _revokeRole(role, account);
    }

    /**
     *  @notice         Revokes role from the account.
     *  @dev            Caller must have the `role`, with caller being the same as `account`.
     *                  Emits {RoleRevoked Event}.
     *
     *  @param role     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     *  @param account  Address of the account from which the role is being revoked.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        if (msg.sender != account) {
            revert PermissionsInvalidPermission(msg.sender, account);
        }
        _revokeRole(role, account);
    }

    /// @dev Sets `adminRole` as `role`'s admin role.
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = _getRoleAdmin[role];
        _getRoleAdmin[role] = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /// @dev Sets up `role` for `account`
    function _setupRole(bytes32 role, address account) internal virtual {
        _hasRole[role][account] = true;
        emit RoleGranted(role, account, msg.sender);
    }

    /// @dev Revokes `role` from `account`
    function _revokeRole(bytes32 role, address account) internal virtual {
        _checkRole(role, account);
        delete _hasRole[role][account];
        emit RoleRevoked(role, account, msg.sender);
    }

    /// @dev Checks `role` for `account`. Reverts with a message including the required role.
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!_hasRole[role][account]) {
            revert PermissionsUnauthorizedAccount(account, role);
        }
    }

    /// @dev Checks `role` for `account`. Reverts with a message including the required role.
    function _checkRoleWithSwitch(bytes32 role, address account) internal view virtual {
        if (!hasRoleWithSwitch(role, account)) {
            revert PermissionsUnauthorizedAccount(account, role);
        }
    }
}

// File: @thirdweb-dev/contracts/extension/interface/IContractMetadata.sol


pragma solidity ^0.8.0;

/// @author thirdweb

/**
 *  Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI
 *  for you contract.
 *
 *  Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea.
 */

interface IContractMetadata {
    /// @dev Returns the metadata URI of the contract.
    function contractURI() external view returns (string memory);

    /**
     *  @dev Sets contract URI for the storefront-level metadata of the contract.
     *       Only module admin can call this function.
     */
    function setContractURI(string calldata _uri) external;

    /// @dev Emitted when the contract URI is updated.
    event ContractURIUpdated(string prevURI, string newURI);
}

// File: @thirdweb-dev/contracts/extension/ContractMetadata.sol


pragma solidity ^0.8.0;

/// @author thirdweb


/**
 *  @title   Contract Metadata
 *  @notice  Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI
 *           for you contract.
 *           Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea.
 */

abstract contract ContractMetadata is IContractMetadata {
    /// @dev The sender is not authorized to perform the action
    error ContractMetadataUnauthorized();

    /// @notice Returns the contract metadata URI.
    string public override contractURI;

    /**
     *  @notice         Lets a contract admin set the URI for contract-level metadata.
     *  @dev            Caller should be authorized to setup contractURI, e.g. contract admin.
     *                  See {_canSetContractURI}.
     *                  Emits {ContractURIUpdated Event}.
     *
     *  @param _uri     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     */
    function setContractURI(string memory _uri) external override {
        if (!_canSetContractURI()) {
            revert ContractMetadataUnauthorized();
        }

        _setupContractURI(_uri);
    }

    /// @dev Lets a contract admin set the URI for contract-level metadata.
    function _setupContractURI(string memory _uri) internal {
        string memory prevURI = contractURI;
        contractURI = _uri;

        emit ContractURIUpdated(prevURI, _uri);
    }

    /// @dev Returns whether contract metadata can be set in the given execution context.
    function _canSetContractURI() internal view virtual returns (bool);
}

// File: @thirdweb-dev/contracts/external-deps/openzeppelin/security/ReentrancyGuard.sol


// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

abstract contract ReentrancyGuard {
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

// File: contracts/PrimapePrediction.sol


pragma solidity ^0.8.26;





/**
 * @title PrimapePrediction
 * @dev A multi-outcome, pari-mutuel style prediction market using the chain's native token for betting.
 *      - Supports multiple outcomes per market.
 *      - Allows early resolution by the owner.
 *      - Includes a platform fee adjustable by the owner.
 *      - Integrates ContractMetadata for contract-level metadata management.
 *      - Integrates Permissions (with owner as default admin) for future role-based expansions.
 */
contract PrimapePrediction is Ownable, ReentrancyGuard, Permissions, ContractMetadata {
    struct Market {
        string question;
        uint256 endTime;
        bool resolved;
        uint256 winningOptionIndex; // If unresolved, set to type(uint256).max
    }

    uint256 public marketCount;
    mapping(uint256 => Market) public markets;

    // Market outcomes: marketId => array of outcome strings
    mapping(uint256 => string[]) public marketOptions;

    // Total shares per option: marketId => optionIndex => total staked
    mapping(uint256 => mapping(uint256 => uint256)) public totalSharesPerOption;

    // User shares per option: marketId => user => optionIndex => shares
    mapping(uint256 => mapping(address => mapping(uint256 => uint256))) public userSharesPerOption;

    // Track if a user has claimed winnings: marketId => user => bool
    mapping(uint256 => mapping(address => bool)) public hasClaimed;

    // Fee in basis points (BPS). 1% = 100 BPS.
    uint256 public feeBps = 100; // Default 1% fee
    uint256 public platformBalance;

    /// @notice Emitted when a new market is created.
    event MarketCreated(
        uint256 indexed marketId,
        string question,
        string[] options,
        uint256 endTime
    );

    /// @notice Emitted when shares are purchased in a market.
    event SharesPurchased(
        uint256 indexed marketId,
        address indexed buyer,
        uint256 optionIndex,
        uint256 amount
    );

    /// @notice Emitted when a market is resolved with a winning option.
    event MarketResolved(uint256 indexed marketId, uint256 winningOptionIndex);

    /// @notice Emitted when winnings are claimed by a user.
    event Claimed(uint256 indexed marketId, address indexed user, uint256 amount);

    /// @notice Emitted when the platform fee BPS is updated.
    event FeeUpdated(uint256 newFeeBps);

    /// @notice Emitted when platform fees are withdrawn.
    event FeesWithdrawn(uint256 amount, address indexed recipient);

    constructor() {
        _setupOwner(msg.sender);
        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
    }

    /**
     * @dev Required override for Ownable extension.
     * @return True if caller is contract owner.
     */
    function _canSetOwner() internal view virtual override returns (bool) {
        return msg.sender == owner();
    }

    /**
     * @dev Required override for ContractMetadata extension to control who can set contract URI.
     * @return True if caller is owner.
     */
    function _canSetContractURI() internal view virtual override returns (bool) {
        return msg.sender == owner();
    }

    /**
     * @notice Create a new prediction market with multiple outcomes.
     * @param _question The market question/prompt.
     * @param _options The array of outcome strings (at least two).
     * @param _duration Duration in seconds the market is active for.
     * @return marketId The ID of the newly created market.
     */
    function createMarket(
        string memory _question,
        string[] memory _options,
        uint256 _duration
    ) external returns (uint256) {
        require(msg.sender == owner(), "Only owner can create markets");
        require(_duration > 0, "Duration must be positive");
        require(_options.length >= 2, "At least two outcomes required");

        uint256 marketId = marketCount++;
        Market storage market = markets[marketId];

        market.question = _question;
        market.endTime = block.timestamp + _duration;
        market.resolved = false;
        market.winningOptionIndex = type(uint256).max;

        for (uint256 i = 0; i < _options.length; i++) {
            marketOptions[marketId].push(_options[i]);
        }

        emit MarketCreated(marketId, _question, _options, market.endTime);
        return marketId;
    }

    /**
     * @notice Buy shares in a specific option of a market using the native token.
     * @param _marketId The ID of the market.
     * @param _optionIndex The index of the chosen outcome.
     */
    function buyShares(
        uint256 _marketId,
        uint256 _optionIndex
    ) external payable {
        Market storage market = markets[_marketId];
        require(block.timestamp < market.endTime, "Market trading period ended");
        require(!market.resolved, "Market already resolved");
        require(_optionIndex < marketOptions[_marketId].length, "Invalid option");
        require(msg.value > 0, "No funds sent");

        uint256 feeAmount = (msg.value * feeBps) / 10000;
        uint256 netAmount = msg.value - feeAmount;

        platformBalance += feeAmount;
        userSharesPerOption[_marketId][msg.sender][_optionIndex] += netAmount;
        totalSharesPerOption[_marketId][_optionIndex] += netAmount;

        emit SharesPurchased(_marketId, msg.sender, _optionIndex, netAmount);
    }

    /**
     * @notice Resolve a market by specifying the winning option.
     * @dev Owner can resolve at any time (early resolution allowed).
     * @param _marketId The market ID.
     * @param _winningOptionIndex The index of the winning outcome.
     */
    function resolveMarket(
        uint256 _marketId,
        uint256 _winningOptionIndex
    ) external {
        require(msg.sender == owner(), "Only owner can resolve");
        Market storage market = markets[_marketId];
        require(!market.resolved, "Already resolved");
        require(_winningOptionIndex < marketOptions[_marketId].length, "Invalid outcome");

        market.winningOptionIndex = _winningOptionIndex;
        market.resolved = true;

        emit MarketResolved(_marketId, _winningOptionIndex);
    }

    /**
     * @notice Claim winnings after a market is resolved.
     * @param _marketId The market ID.
     */
    function claimWinnings(uint256 _marketId) external nonReentrant {
        Market storage market = markets[_marketId];
        require(market.resolved, "Market not resolved");
        require(!hasClaimed[_marketId][msg.sender], "Already claimed");

        uint256 winningOption = market.winningOptionIndex;
        uint256 userShares = userSharesPerOption[_marketId][msg.sender][winningOption];
        require(userShares > 0, "No winnings");

        uint256 winningShares = totalSharesPerOption[_marketId][winningOption];
        uint256 losingShares;
        uint256 optionCount = marketOptions[_marketId].length;
        for (uint256 i = 0; i < optionCount; i++) {
            if (i != winningOption) {
                losingShares += totalSharesPerOption[_marketId][i];
            }
        }

        uint256 rewardRatio = 0;
        if (winningShares > 0) {
            rewardRatio = (losingShares * 1e18) / winningShares;
        }
        uint256 winnings = userShares + (userShares * rewardRatio) / 1e18;

        userSharesPerOption[_marketId][msg.sender][winningOption] = 0;
        hasClaimed[_marketId][msg.sender] = true;

        (bool success, ) = payable(msg.sender).call{value: winnings}("");
        require(success, "Transfer failed");

        emit Claimed(_marketId, msg.sender, winnings);
    }

    /**
     * @notice Batch claim winnings for multiple users.
     * @param _marketId The market ID.
     * @param _users Array of addresses to claim for.
     */
    function batchClaimWinnings(
        uint256 _marketId,
        address[] calldata _users
    ) external nonReentrant {
        Market storage market = markets[_marketId];
        require(market.resolved, "Market not resolved yet");

        uint256 winningOption = market.winningOptionIndex;
        uint256 winningShares = totalSharesPerOption[_marketId][winningOption];
        uint256 losingShares;
        uint256 optionCount = marketOptions[_marketId].length;
        for (uint256 i = 0; i < optionCount; i++) {
            if (i != winningOption) {
                losingShares += totalSharesPerOption[_marketId][i];
            }
        }

        uint256 rewardRatio = 0;
        if (winningShares > 0) {
            rewardRatio = (losingShares * 1e18) / winningShares;
        }

        for (uint256 i = 0; i < _users.length; i++) {
            address user = _users[i];
            if (hasClaimed[_marketId][user]) {
                continue;
            }

            uint256 userShares = userSharesPerOption[_marketId][user][winningOption];
            if (userShares == 0) {
                continue;
            }

            uint256 winnings = userShares + (userShares * rewardRatio) / 1e18;
            hasClaimed[_marketId][user] = true;
            userSharesPerOption[_marketId][user][winningOption] = 0;

            (bool success, ) = payable(user).call{value: winnings}("");
            require(success, "Transfer failed");
            emit Claimed(_marketId, user, winnings);
        }
    }

    /**
     * @notice Get the basic info of a market.
     * @param _marketId The market ID.
     * @return question The market's question.
     * @return endTime The market's end time.
     * @return resolved Whether the market is resolved.
     * @return winningOptionIndex The winning option index or max uint if unresolved.
     */
    function getMarketInfo(
        uint256 _marketId
    )
        external
        view
        returns (
            string memory question,
            uint256 endTime,
            bool resolved,
            uint256 winningOptionIndex
        )
    {
        Market storage market = markets[_marketId];
        return (
            market.question,
            market.endTime,
            market.resolved,
            market.winningOptionIndex
        );
    }

    /**
     * @notice Get the options of a market.
     * @param _marketId The market ID.
     * @return Array of outcome option strings.
     */
    function getMarketOptions(uint256 _marketId) external view returns (string[] memory) {
        string[] memory opts = new string[](marketOptions[_marketId].length);
        for (uint256 i = 0; i < marketOptions[_marketId].length; i++) {
            opts[i] = marketOptions[_marketId][i];
        }
        return opts;
    }

    /**
     * @notice Get user shares for each option in a market.
     * @param _marketId The market ID.
     * @param _user The user address.
     * @return balances Array of user shares per option.
     */
    function getUserShares(
        uint256 _marketId,
        address _user
    ) external view returns (uint256[] memory balances) {
        uint256 optionCount = marketOptions[_marketId].length;
        balances = new uint256[](optionCount);
        for (uint256 i = 0; i < optionCount; i++) {
            balances[i] = userSharesPerOption[_marketId][_user][i];
        }
    }

    /**
     * @notice Update the fee in basis points.
     * @param _feeBps The new fee in BPS. (e.g., 100 = 1%)
     */
    function setFeeBps(uint256 _feeBps) external onlyOwner {
        require(_feeBps <= 1000, "Fee too high"); // max 10%
        feeBps = _feeBps;
        emit FeeUpdated(_feeBps);
    }

    /**
     * @notice Owner can withdraw accumulated platform fees.
     * @param _recipient Address to receive withdrawn fees.
     * @param _amount Amount of fees to withdraw (in wei).
     */
    function withdrawFees(address payable _recipient, uint256 _amount) external onlyOwner nonReentrant {
        require(_amount <= platformBalance, "Not enough fees");
        platformBalance -= _amount;
        (bool success, ) = _recipient.call{value: _amount}("");
        require(success, "Withdraw failed");

        emit FeesWithdrawn(_amount, _recipient);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ContractMetadataUnauthorized","type":"error"},{"inputs":[],"name":"OwnableUnauthorized","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"PermissionsAlreadyGranted","type":"error"},{"inputs":[{"internalType":"address","name":"expected","type":"address"},{"internalType":"address","name":"actual","type":"address"}],"name":"PermissionsInvalidPermission","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"PermissionsUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"prevURI","type":"string"},{"indexed":false,"internalType":"string","name":"newURI","type":"string"}],"name":"ContractURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFeeBps","type":"uint256"}],"name":"FeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"string","name":"question","type":"string"},{"indexed":false,"internalType":"string[]","name":"options","type":"string[]"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"MarketCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"winningOptionIndex","type":"uint256"}],"name":"MarketResolved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"prevOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"optionIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SharesPurchased","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketId","type":"uint256"},{"internalType":"address[]","name":"_users","type":"address[]"}],"name":"batchClaimWinnings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketId","type":"uint256"},{"internalType":"uint256","name":"_optionIndex","type":"uint256"}],"name":"buyShares","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketId","type":"uint256"}],"name":"claimWinnings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_question","type":"string"},{"internalType":"string[]","name":"_options","type":"string[]"},{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"createMarket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketId","type":"uint256"}],"name":"getMarketInfo","outputs":[{"internalType":"string","name":"question","type":"string"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bool","name":"resolved","type":"bool"},{"internalType":"uint256","name":"winningOptionIndex","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketId","type":"uint256"}],"name":"getMarketOptions","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketId","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"getUserShares","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"hasClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRoleWithSwitch","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"marketOptions","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"markets","outputs":[{"internalType":"string","name":"question","type":"string"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bool","name":"resolved","type":"bool"},{"internalType":"uint256","name":"winningOptionIndex","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketId","type":"uint256"},{"internalType":"uint256","name":"_winningOptionIndex","type":"uint256"}],"name":"resolveMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_feeBps","type":"uint256"}],"name":"setFeeBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalSharesPerOption","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userSharesPerOption","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526064600b553480156013575f80fd5b5060018055601f33602b565b60275f33607a565b60d4565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a35050565b5f8281526002602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b612326806100e15f395ff3fe6080604052600436106101ba575f3560e01c8063835dc40b116100f2578063ad2b69bc11610092578063d547741f11610062578063d547741f1461055a578063e8a3d48514610579578063ec9790821461058d578063fbc529cb146105a2575f80fd5b8063ad2b69bc146104cd578063ad3b1b4714610509578063b1283e7714610528578063beebc5da14610547575f80fd5b806391d14854116100cd57806391d148541461045d578063938e3d7b1461047c578063a217fddf1461049b578063a32fa5b3146104ae575f80fd5b8063835dc40b146103c2578063873f6f9e146103ee5780638da5cb5b14610437575f80fd5b80633bdfa9821161015d5780636055733311610138578063605573331461035057806362a5dbbc1461036f578063677bd9ff1461038457806372c27b62146103a3575f80fd5b80633bdfa982146102bf5780633ec79193146102eb57806356d334041461031a575f80fd5b806324a9d8531161019857806324a9d8531461024d57806327536b28146102625780632f2ff15d1461028157806336568abe146102a0575f80fd5b806305d45d5f146101be57806313af4035146101f3578063248a9ca314610214575b5f80fd5b3480156101c9575f80fd5b506101dd6101d8366004611c01565b6105c1565b6040516101ea9190611ca0565b60405180910390f35b3480156101fe575f80fd5b5061021261020d366004611ccd565b610712565b005b34801561021f575f80fd5b5061023f61022e366004611c01565b5f9081526003602052604090205490565b6040519081526020016101ea565b348015610258575f80fd5b5061023f600b5481565b34801561026d575f80fd5b5061021261027c366004611ce8565b610748565b34801561028c575f80fd5b5061021261029b366004611d62565b610ab7565b3480156102ab575f80fd5b506102126102ba366004611d62565b610b32565b3480156102ca575f80fd5b506102de6102d9366004611d90565b610b76565b6040516101ea9190611db0565b3480156102f6575f80fd5b5061030a610305366004611c01565b610c27565b6040516101ea9493929190611dc2565b348015610325575f80fd5b5061023f610334366004611d90565b600860209081525f928352604080842090915290825290205481565b34801561035b575f80fd5b5061021261036a366004611d90565b610cf0565b34801561037a575f80fd5b5061023f600c5481565b34801561038f575f80fd5b5061021261039e366004611c01565b610e3c565b3480156103ae575f80fd5b506102126103bd366004611c01565b61113d565b3480156103cd575f80fd5b506103e16103dc366004611d62565b6111e3565b6040516101ea9190611df0565b3480156103f9575f80fd5b50610427610408366004611d62565b600a60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016101ea565b348015610442575f80fd5b505f546040516001600160a01b0390911681526020016101ea565b348015610468575f80fd5b50610427610477366004611d62565b61129c565b348015610487575f80fd5b50610212610496366004611ee3565b6112c8565b3480156104a6575f80fd5b5061023f5f81565b3480156104b9575f80fd5b506104276104c8366004611d62565b6112fb565b3480156104d8575f80fd5b5061023f6104e7366004611f1d565b600960209081525f938452604080852082529284528284209052825290205481565b348015610514575f80fd5b50610212610523366004611f52565b61134f565b348015610533575f80fd5b5061030a610542366004611c01565b6114d6565b610212610555366004611d90565b611589565b348015610565575f80fd5b50610212610574366004611d62565b6117b1565b348015610584575f80fd5b506102de6117c9565b348015610598575f80fd5b5061023f60055481565b3480156105ad575f80fd5b5061023f6105bc366004611f7c565b6117d6565b5f818152600760205260408120546060919067ffffffffffffffff8111156105eb576105eb611e32565b60405190808252806020026020018201604052801561061e57816020015b60608152602001906001900390816106095790505b5090505f5b5f8481526007602052604090205481101561070b575f8481526007602052604090208054829081106106575761065761207c565b905f5260205f2001805461066a90612090565b80601f016020809104026020016040519081016040528092919081815260200182805461069690612090565b80156106e15780601f106106b8576101008083540402835291602001916106e1565b820191905f5260205f20905b8154815290600101906020018083116106c457829003601f168201915b50505050508282815181106106f8576106f861207c565b6020908102919091010152600101610623565b5092915050565b5f546001600160a01b0316331461073c576040516316ccb9cb60e11b815260040160405180910390fd5b610745816119ca565b50565b6002600154036107735760405162461bcd60e51b815260040161076a906120c8565b60405180910390fd5b600260018190555f8481526006602052604090209081015460ff166107da5760405162461bcd60e51b815260206004820152601760248201527f4d61726b6574206e6f74207265736f6c76656420796574000000000000000000604482015260640161076a565b60038101545f8581526008602090815260408083208484528252808320548884526007909252822054909190815b818110156108455784811461083d575f89815260086020908152604080832084845290915290205461083a9084612113565b92505b600101610808565b505f831561086d578361086084670de0b6b3a7640000612126565b61086a919061213d565b90505b5f5b87811015610aa7575f89898381811061088a5761088a61207c565b905060200201602081019061089f9190611ccd565b5f8c8152600a602090815260408083206001600160a01b038516845290915290205490915060ff16156108d25750610a9f565b5f8b81526009602090815260408083206001600160a01b038516845282528083208a84529091528120549081900361090b575050610a9f565b5f670de0b6b3a764000061091f8684612126565b610929919061213d565b6109339083612113565b90506001600a5f8f81526020019081526020015f205f856001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548160ff0219169083151502179055505f60095f8f81526020019081526020015f205f856001600160a01b03166001600160a01b031681526020019081526020015f205f8b81526020019081526020015f20819055505f836001600160a01b0316826040515f6040518083038185875af1925050503d805f8114610a0e576040519150601f19603f3d011682016040523d82523d5f602084013e610a13565b606091505b5050905080610a565760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015260640161076a565b836001600160a01b03168e7f4ec90e965519d92681267467f775ada5bd214aa92c0dc93d90a5e880ce9ed02684604051610a9291815260200190565b60405180910390a3505050505b60010161086f565b5050600180555050505050505050565b5f82815260036020526040902054610acf9033611a19565b5f8281526002602090815260408083206001600160a01b038516845290915290205460ff1615610b2457604051636a4e0b3560e11b81526001600160a01b03821660048201526024810183905260440161076a565b610b2e8282611a6d565b5050565b336001600160a01b03821614610b6c576040516320b4e31160e11b81523360048201526001600160a01b038216602482015260440161076a565b610b2e8282611ac7565b6007602052815f5260405f208181548110610b8f575f80fd5b905f5260205f20015f91509150508054610ba890612090565b80601f0160208091040260200160405190810160405280929190818152602001828054610bd490612090565b8015610c1f5780601f10610bf657610100808354040283529160200191610c1f565b820191905f5260205f20905b815481529060010190602001808311610c0257829003601f168201915b505050505081565b5f8181526006602052604081206001810154600282015460038301548354606095948594859491938493919260ff16918490610c6290612090565b80601f0160208091040260200160405190810160405280929190818152602001828054610c8e90612090565b8015610cd95780601f10610cb057610100808354040283529160200191610cd9565b820191905f5260205f20905b815481529060010190602001808311610cbc57829003601f168201915b505050505093509450945094509450509193509193565b5f546001600160a01b03163314610d425760405162461bcd60e51b81526020600482015260166024820152754f6e6c79206f776e65722063616e207265736f6c766560501b604482015260640161076a565b5f828152600660205260409020600281015460ff1615610d975760405162461bcd60e51b815260206004820152601060248201526f105b1c9958591e481c995cdbdb1d995960821b604482015260640161076a565b5f838152600760205260409020548210610de55760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206f7574636f6d6560881b604482015260640161076a565b6003810182905560028101805460ff1916600117905560405183907f6dfc24f0f2fb42e49fb4fa3ffa8abb148cab908a1fb8335b3f128a08b2594af190610e2f9085815260200190565b60405180910390a2505050565b600260015403610e5e5760405162461bcd60e51b815260040161076a906120c8565b600260018190555f8281526006602052604090209081015460ff16610ebb5760405162461bcd60e51b815260206004820152601360248201527213585c9ad95d081b9bdd081c995cdbdb1d9959606a1b604482015260640161076a565b5f828152600a6020908152604080832033845290915290205460ff1615610f165760405162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e4818db185a5b5959608a1b604482015260640161076a565b60038101545f838152600960209081526040808320338452825280832084845290915290205480610f775760405162461bcd60e51b815260206004820152600b60248201526a4e6f2077696e6e696e677360a81b604482015260640161076a565b5f8481526008602090815260408083208584528252808320548784526007909252822054909190815b81811015610fdd57858114610fd5575f888152600860209081526040808320848452909152902054610fd29084612113565b92505b600101610fa0565b505f83156110055783610ff884670de0b6b3a7640000612126565b611002919061213d565b90505b5f670de0b6b3a76400006110198388612126565b611023919061213d565b61102d9087612113565b5f8a8152600960209081526040808320338085529083528184208c855283528184208490558d8452600a8352818420818552909252808320805460ff1916600117905551929350909183908381818185875af1925050503d805f81146110ae576040519150601f19603f3d011682016040523d82523d5f602084013e6110b3565b606091505b50509050806110f65760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015260640161076a565b60405182815233908b907f4ec90e965519d92681267467f775ada5bd214aa92c0dc93d90a5e880ce9ed0269060200160405180910390a35050600180555050505050505050565b5f546001600160a01b03163314611167576040516316ccb9cb60e11b815260040160405180910390fd5b6103e88111156111a85760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b604482015260640161076a565b600b8190556040518181527f8c4d35e54a3f2ef1134138fd8ea3daee6a3c89e10d2665996babdf70261e2c769060200160405180910390a150565b5f828152600760205260409020546060908067ffffffffffffffff81111561120d5761120d611e32565b604051908082528060200260200182016040528015611236578160200160208202803683370190505b5091505f5b81811015611294575f8581526009602090815260408083206001600160a01b0388168452825280832084845290915290205483518490839081106112815761128161207c565b602090810291909101015260010161123b565b505092915050565b5f8281526002602090815260408083206001600160a01b038516845290915290205460ff165b92915050565b5f546001600160a01b031633146112f257604051639f7f092560e01b815260040160405180910390fd5b61074581611b28565b5f82815260026020908152604080832083805290915281205460ff1661134657505f8281526002602090815260408083206001600160a01b038516845290915290205460ff166112c2565b50600192915050565b5f546001600160a01b03163314611379576040516316ccb9cb60e11b815260040160405180910390fd5b60026001540361139b5760405162461bcd60e51b815260040161076a906120c8565b6002600155600c548111156113e45760405162461bcd60e51b815260206004820152600f60248201526e4e6f7420656e6f756768206665657360881b604482015260640161076a565b80600c5f8282546113f5919061215c565b90915550506040515f906001600160a01b0384169083908381818185875af1925050503d805f8114611442576040519150601f19603f3d011682016040523d82523d5f602084013e611447565b606091505b505090508061148a5760405162461bcd60e51b815260206004820152600f60248201526e15da5d1a191c985dc819985a5b1959608a1b604482015260640161076a565b826001600160a01b03167f812bcf6853ebc81dc0a1d2323893eedad6cd086a4398311a699e0a7acdf187b3836040516114c591815260200190565b60405180910390a250506001805550565b60066020525f90815260409020805481906114f090612090565b80601f016020809104026020016040519081016040528092919081815260200182805461151c90612090565b80156115675780601f1061153e57610100808354040283529160200191611567565b820191905f5260205f20905b81548152906001019060200180831161154a57829003601f168201915b50505050600183015460028401546003909401549293909260ff909116915084565b5f828152600660205260409020600181015442106115e95760405162461bcd60e51b815260206004820152601b60248201527f4d61726b65742074726164696e6720706572696f6420656e6465640000000000604482015260640161076a565b600281015460ff161561163e5760405162461bcd60e51b815260206004820152601760248201527f4d61726b657420616c7265616479207265736f6c766564000000000000000000604482015260640161076a565b5f83815260076020526040902054821061168b5760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21037b83a34b7b760911b604482015260640161076a565b5f34116116ca5760405162461bcd60e51b815260206004820152600d60248201526c139bc8199d5b991cc81cd95b9d609a1b604482015260640161076a565b5f612710600b54346116dc9190612126565b6116e6919061213d565b90505f6116f3823461215c565b905081600c5f8282546117069190612113565b90915550505f85815260096020908152604080832033845282528083208784529091528120805483929061173b908490612113565b90915550505f85815260086020908152604080832087845290915281208054839290611768908490612113565b90915550506040805185815260208101839052339187917fce81571c08c76465bdf390ad1abe80af8c51c6c4566e3485f9395f13d5ad6328910160405180910390a35050505050565b5f82815260036020526040902054610b6c9033611a19565b60048054610ba890612090565b5f80546001600160a01b031633146118305760405162461bcd60e51b815260206004820152601d60248201527f4f6e6c79206f776e65722063616e20637265617465206d61726b657473000000604482015260640161076a565b5f821161187f5760405162461bcd60e51b815260206004820152601960248201527f4475726174696f6e206d75737420626520706f73697469766500000000000000604482015260640161076a565b6002835110156118d15760405162461bcd60e51b815260206004820152601e60248201527f4174206c656173742074776f206f7574636f6d65732072657175697265640000604482015260640161076a565b600580545f91826118e18361216f565b909155505f8181526006602052604090209091508061190087826121d3565b5061190b8442612113565b600182015560028101805460ff191690555f1960038201555f5b8551811015611980575f838152600760205260409020865187908390811061194f5761194f61207c565b60209081029190910181015182546001810184555f93845291909220019061197790826121d3565b50600101611925565b50817fdb6ae5c511cd814e8b6d7dd1f64d32f3bd488e4361486cdcfa2e2debaeddca87878784600101546040516119b99392919061228e565b60405180910390a250949350505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a35050565b5f8281526002602090815260408083206001600160a01b038516845290915290205460ff16610b2e5760405163043c588360e11b81526001600160a01b03821660048201526024810183905260440161076a565b5f8281526002602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b611ad18282611a19565b5f8281526002602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b5f60048054611b3690612090565b80601f0160208091040260200160405190810160405280929190818152602001828054611b6290612090565b8015611bad5780601f10611b8457610100808354040283529160200191611bad565b820191905f5260205f20905b815481529060010190602001808311611b9057829003601f168201915b505050505090508160049081611bc391906121d3565b507fc9c7c3fe08b88b4df9d4d47ef47d2c43d55c025a0ba88ca442580ed9e7348a168183604051611bf59291906122c3565b60405180910390a15050565b5f60208284031215611c11575f80fd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f82825180855260208501945060208160051b830101602085015f5b83811015611c9457601f19858403018852611c7e838351611c18565b6020988901989093509190910190600101611c62565b50909695505050505050565b602081525f611cb26020830184611c46565b9392505050565b6001600160a01b0381168114610745575f80fd5b5f60208284031215611cdd575f80fd5b8135611cb281611cb9565b5f805f60408486031215611cfa575f80fd5b83359250602084013567ffffffffffffffff811115611d17575f80fd5b8401601f81018613611d27575f80fd5b803567ffffffffffffffff811115611d3d575f80fd5b8660208260051b8401011115611d51575f80fd5b939660209190910195509293505050565b5f8060408385031215611d73575f80fd5b823591506020830135611d8581611cb9565b809150509250929050565b5f8060408385031215611da1575f80fd5b50508035926020909101359150565b602081525f611cb26020830184611c18565b608081525f611dd46080830187611c18565b6020830195909552509115156040830152606090910152919050565b602080825282518282018190525f918401906040840190835b81811015611e27578351835260209384019390920191600101611e09565b509095945050505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611e6f57611e6f611e32565b604052919050565b5f82601f830112611e86575f80fd5b813567ffffffffffffffff811115611ea057611ea0611e32565b611eb3601f8201601f1916602001611e46565b818152846020838601011115611ec7575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60208284031215611ef3575f80fd5b813567ffffffffffffffff811115611f09575f80fd5b611f1584828501611e77565b949350505050565b5f805f60608486031215611f2f575f80fd5b833592506020840135611f4181611cb9565b929592945050506040919091013590565b5f8060408385031215611f63575f80fd5b8235611f6e81611cb9565b946020939093013593505050565b5f805f60608486031215611f8e575f80fd5b833567ffffffffffffffff811115611fa4575f80fd5b611fb086828701611e77565b935050602084013567ffffffffffffffff811115611fcc575f80fd5b8401601f81018613611fdc575f80fd5b803567ffffffffffffffff811115611ff657611ff6611e32565b8060051b61200660208201611e46565b91825260208184018101929081019089841115612021575f80fd5b6020850192505b8383101561206757823567ffffffffffffffff811115612046575f80fd5b6120558b602083890101611e77565b83525060209283019290910190612028565b96999698505050506040949094013593505050565b634e487b7160e01b5f52603260045260245ffd5b600181811c908216806120a457607f821691505b6020821081036120c257634e487b7160e01b5f52602260045260245ffd5b50919050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b808201808211156112c2576112c26120ff565b80820281158282048414176112c2576112c26120ff565b5f8261215757634e487b7160e01b5f52601260045260245ffd5b500490565b818103818111156112c2576112c26120ff565b5f60018201612180576121806120ff565b5060010190565b601f8211156121ce57805f5260205f20601f840160051c810160208510156121ac5750805b601f840160051c820191505b818110156121cb575f81556001016121b8565b50505b505050565b815167ffffffffffffffff8111156121ed576121ed611e32565b612201816121fb8454612090565b84612187565b6020601f821160018114612233575f831561221c5750848201515b5f19600385901b1c1916600184901b1784556121cb565b5f84815260208120601f198516915b828110156122625787850151825560209485019460019092019101612242565b508482101561227f57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b606081525f6122a06060830186611c18565b82810360208401526122b28186611c46565b915050826040830152949350505050565b604081525f6122d56040830185611c18565b82810360208401526122e78185611c18565b9594505050505056fea2646970667358221220ba074de1fa58c3a3fcf333722514af5d85c4a236760da3d21f43d0abcd15cb1e64736f6c634300081a0033

Deployed Bytecode

0x6080604052600436106101ba575f3560e01c8063835dc40b116100f2578063ad2b69bc11610092578063d547741f11610062578063d547741f1461055a578063e8a3d48514610579578063ec9790821461058d578063fbc529cb146105a2575f80fd5b8063ad2b69bc146104cd578063ad3b1b4714610509578063b1283e7714610528578063beebc5da14610547575f80fd5b806391d14854116100cd57806391d148541461045d578063938e3d7b1461047c578063a217fddf1461049b578063a32fa5b3146104ae575f80fd5b8063835dc40b146103c2578063873f6f9e146103ee5780638da5cb5b14610437575f80fd5b80633bdfa9821161015d5780636055733311610138578063605573331461035057806362a5dbbc1461036f578063677bd9ff1461038457806372c27b62146103a3575f80fd5b80633bdfa982146102bf5780633ec79193146102eb57806356d334041461031a575f80fd5b806324a9d8531161019857806324a9d8531461024d57806327536b28146102625780632f2ff15d1461028157806336568abe146102a0575f80fd5b806305d45d5f146101be57806313af4035146101f3578063248a9ca314610214575b5f80fd5b3480156101c9575f80fd5b506101dd6101d8366004611c01565b6105c1565b6040516101ea9190611ca0565b60405180910390f35b3480156101fe575f80fd5b5061021261020d366004611ccd565b610712565b005b34801561021f575f80fd5b5061023f61022e366004611c01565b5f9081526003602052604090205490565b6040519081526020016101ea565b348015610258575f80fd5b5061023f600b5481565b34801561026d575f80fd5b5061021261027c366004611ce8565b610748565b34801561028c575f80fd5b5061021261029b366004611d62565b610ab7565b3480156102ab575f80fd5b506102126102ba366004611d62565b610b32565b3480156102ca575f80fd5b506102de6102d9366004611d90565b610b76565b6040516101ea9190611db0565b3480156102f6575f80fd5b5061030a610305366004611c01565b610c27565b6040516101ea9493929190611dc2565b348015610325575f80fd5b5061023f610334366004611d90565b600860209081525f928352604080842090915290825290205481565b34801561035b575f80fd5b5061021261036a366004611d90565b610cf0565b34801561037a575f80fd5b5061023f600c5481565b34801561038f575f80fd5b5061021261039e366004611c01565b610e3c565b3480156103ae575f80fd5b506102126103bd366004611c01565b61113d565b3480156103cd575f80fd5b506103e16103dc366004611d62565b6111e3565b6040516101ea9190611df0565b3480156103f9575f80fd5b50610427610408366004611d62565b600a60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016101ea565b348015610442575f80fd5b505f546040516001600160a01b0390911681526020016101ea565b348015610468575f80fd5b50610427610477366004611d62565b61129c565b348015610487575f80fd5b50610212610496366004611ee3565b6112c8565b3480156104a6575f80fd5b5061023f5f81565b3480156104b9575f80fd5b506104276104c8366004611d62565b6112fb565b3480156104d8575f80fd5b5061023f6104e7366004611f1d565b600960209081525f938452604080852082529284528284209052825290205481565b348015610514575f80fd5b50610212610523366004611f52565b61134f565b348015610533575f80fd5b5061030a610542366004611c01565b6114d6565b610212610555366004611d90565b611589565b348015610565575f80fd5b50610212610574366004611d62565b6117b1565b348015610584575f80fd5b506102de6117c9565b348015610598575f80fd5b5061023f60055481565b3480156105ad575f80fd5b5061023f6105bc366004611f7c565b6117d6565b5f818152600760205260408120546060919067ffffffffffffffff8111156105eb576105eb611e32565b60405190808252806020026020018201604052801561061e57816020015b60608152602001906001900390816106095790505b5090505f5b5f8481526007602052604090205481101561070b575f8481526007602052604090208054829081106106575761065761207c565b905f5260205f2001805461066a90612090565b80601f016020809104026020016040519081016040528092919081815260200182805461069690612090565b80156106e15780601f106106b8576101008083540402835291602001916106e1565b820191905f5260205f20905b8154815290600101906020018083116106c457829003601f168201915b50505050508282815181106106f8576106f861207c565b6020908102919091010152600101610623565b5092915050565b5f546001600160a01b0316331461073c576040516316ccb9cb60e11b815260040160405180910390fd5b610745816119ca565b50565b6002600154036107735760405162461bcd60e51b815260040161076a906120c8565b60405180910390fd5b600260018190555f8481526006602052604090209081015460ff166107da5760405162461bcd60e51b815260206004820152601760248201527f4d61726b6574206e6f74207265736f6c76656420796574000000000000000000604482015260640161076a565b60038101545f8581526008602090815260408083208484528252808320548884526007909252822054909190815b818110156108455784811461083d575f89815260086020908152604080832084845290915290205461083a9084612113565b92505b600101610808565b505f831561086d578361086084670de0b6b3a7640000612126565b61086a919061213d565b90505b5f5b87811015610aa7575f89898381811061088a5761088a61207c565b905060200201602081019061089f9190611ccd565b5f8c8152600a602090815260408083206001600160a01b038516845290915290205490915060ff16156108d25750610a9f565b5f8b81526009602090815260408083206001600160a01b038516845282528083208a84529091528120549081900361090b575050610a9f565b5f670de0b6b3a764000061091f8684612126565b610929919061213d565b6109339083612113565b90506001600a5f8f81526020019081526020015f205f856001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548160ff0219169083151502179055505f60095f8f81526020019081526020015f205f856001600160a01b03166001600160a01b031681526020019081526020015f205f8b81526020019081526020015f20819055505f836001600160a01b0316826040515f6040518083038185875af1925050503d805f8114610a0e576040519150601f19603f3d011682016040523d82523d5f602084013e610a13565b606091505b5050905080610a565760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015260640161076a565b836001600160a01b03168e7f4ec90e965519d92681267467f775ada5bd214aa92c0dc93d90a5e880ce9ed02684604051610a9291815260200190565b60405180910390a3505050505b60010161086f565b5050600180555050505050505050565b5f82815260036020526040902054610acf9033611a19565b5f8281526002602090815260408083206001600160a01b038516845290915290205460ff1615610b2457604051636a4e0b3560e11b81526001600160a01b03821660048201526024810183905260440161076a565b610b2e8282611a6d565b5050565b336001600160a01b03821614610b6c576040516320b4e31160e11b81523360048201526001600160a01b038216602482015260440161076a565b610b2e8282611ac7565b6007602052815f5260405f208181548110610b8f575f80fd5b905f5260205f20015f91509150508054610ba890612090565b80601f0160208091040260200160405190810160405280929190818152602001828054610bd490612090565b8015610c1f5780601f10610bf657610100808354040283529160200191610c1f565b820191905f5260205f20905b815481529060010190602001808311610c0257829003601f168201915b505050505081565b5f8181526006602052604081206001810154600282015460038301548354606095948594859491938493919260ff16918490610c6290612090565b80601f0160208091040260200160405190810160405280929190818152602001828054610c8e90612090565b8015610cd95780601f10610cb057610100808354040283529160200191610cd9565b820191905f5260205f20905b815481529060010190602001808311610cbc57829003601f168201915b505050505093509450945094509450509193509193565b5f546001600160a01b03163314610d425760405162461bcd60e51b81526020600482015260166024820152754f6e6c79206f776e65722063616e207265736f6c766560501b604482015260640161076a565b5f828152600660205260409020600281015460ff1615610d975760405162461bcd60e51b815260206004820152601060248201526f105b1c9958591e481c995cdbdb1d995960821b604482015260640161076a565b5f838152600760205260409020548210610de55760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206f7574636f6d6560881b604482015260640161076a565b6003810182905560028101805460ff1916600117905560405183907f6dfc24f0f2fb42e49fb4fa3ffa8abb148cab908a1fb8335b3f128a08b2594af190610e2f9085815260200190565b60405180910390a2505050565b600260015403610e5e5760405162461bcd60e51b815260040161076a906120c8565b600260018190555f8281526006602052604090209081015460ff16610ebb5760405162461bcd60e51b815260206004820152601360248201527213585c9ad95d081b9bdd081c995cdbdb1d9959606a1b604482015260640161076a565b5f828152600a6020908152604080832033845290915290205460ff1615610f165760405162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e4818db185a5b5959608a1b604482015260640161076a565b60038101545f838152600960209081526040808320338452825280832084845290915290205480610f775760405162461bcd60e51b815260206004820152600b60248201526a4e6f2077696e6e696e677360a81b604482015260640161076a565b5f8481526008602090815260408083208584528252808320548784526007909252822054909190815b81811015610fdd57858114610fd5575f888152600860209081526040808320848452909152902054610fd29084612113565b92505b600101610fa0565b505f83156110055783610ff884670de0b6b3a7640000612126565b611002919061213d565b90505b5f670de0b6b3a76400006110198388612126565b611023919061213d565b61102d9087612113565b5f8a8152600960209081526040808320338085529083528184208c855283528184208490558d8452600a8352818420818552909252808320805460ff1916600117905551929350909183908381818185875af1925050503d805f81146110ae576040519150601f19603f3d011682016040523d82523d5f602084013e6110b3565b606091505b50509050806110f65760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015260640161076a565b60405182815233908b907f4ec90e965519d92681267467f775ada5bd214aa92c0dc93d90a5e880ce9ed0269060200160405180910390a35050600180555050505050505050565b5f546001600160a01b03163314611167576040516316ccb9cb60e11b815260040160405180910390fd5b6103e88111156111a85760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b604482015260640161076a565b600b8190556040518181527f8c4d35e54a3f2ef1134138fd8ea3daee6a3c89e10d2665996babdf70261e2c769060200160405180910390a150565b5f828152600760205260409020546060908067ffffffffffffffff81111561120d5761120d611e32565b604051908082528060200260200182016040528015611236578160200160208202803683370190505b5091505f5b81811015611294575f8581526009602090815260408083206001600160a01b0388168452825280832084845290915290205483518490839081106112815761128161207c565b602090810291909101015260010161123b565b505092915050565b5f8281526002602090815260408083206001600160a01b038516845290915290205460ff165b92915050565b5f546001600160a01b031633146112f257604051639f7f092560e01b815260040160405180910390fd5b61074581611b28565b5f82815260026020908152604080832083805290915281205460ff1661134657505f8281526002602090815260408083206001600160a01b038516845290915290205460ff166112c2565b50600192915050565b5f546001600160a01b03163314611379576040516316ccb9cb60e11b815260040160405180910390fd5b60026001540361139b5760405162461bcd60e51b815260040161076a906120c8565b6002600155600c548111156113e45760405162461bcd60e51b815260206004820152600f60248201526e4e6f7420656e6f756768206665657360881b604482015260640161076a565b80600c5f8282546113f5919061215c565b90915550506040515f906001600160a01b0384169083908381818185875af1925050503d805f8114611442576040519150601f19603f3d011682016040523d82523d5f602084013e611447565b606091505b505090508061148a5760405162461bcd60e51b815260206004820152600f60248201526e15da5d1a191c985dc819985a5b1959608a1b604482015260640161076a565b826001600160a01b03167f812bcf6853ebc81dc0a1d2323893eedad6cd086a4398311a699e0a7acdf187b3836040516114c591815260200190565b60405180910390a250506001805550565b60066020525f90815260409020805481906114f090612090565b80601f016020809104026020016040519081016040528092919081815260200182805461151c90612090565b80156115675780601f1061153e57610100808354040283529160200191611567565b820191905f5260205f20905b81548152906001019060200180831161154a57829003601f168201915b50505050600183015460028401546003909401549293909260ff909116915084565b5f828152600660205260409020600181015442106115e95760405162461bcd60e51b815260206004820152601b60248201527f4d61726b65742074726164696e6720706572696f6420656e6465640000000000604482015260640161076a565b600281015460ff161561163e5760405162461bcd60e51b815260206004820152601760248201527f4d61726b657420616c7265616479207265736f6c766564000000000000000000604482015260640161076a565b5f83815260076020526040902054821061168b5760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21037b83a34b7b760911b604482015260640161076a565b5f34116116ca5760405162461bcd60e51b815260206004820152600d60248201526c139bc8199d5b991cc81cd95b9d609a1b604482015260640161076a565b5f612710600b54346116dc9190612126565b6116e6919061213d565b90505f6116f3823461215c565b905081600c5f8282546117069190612113565b90915550505f85815260096020908152604080832033845282528083208784529091528120805483929061173b908490612113565b90915550505f85815260086020908152604080832087845290915281208054839290611768908490612113565b90915550506040805185815260208101839052339187917fce81571c08c76465bdf390ad1abe80af8c51c6c4566e3485f9395f13d5ad6328910160405180910390a35050505050565b5f82815260036020526040902054610b6c9033611a19565b60048054610ba890612090565b5f80546001600160a01b031633146118305760405162461bcd60e51b815260206004820152601d60248201527f4f6e6c79206f776e65722063616e20637265617465206d61726b657473000000604482015260640161076a565b5f821161187f5760405162461bcd60e51b815260206004820152601960248201527f4475726174696f6e206d75737420626520706f73697469766500000000000000604482015260640161076a565b6002835110156118d15760405162461bcd60e51b815260206004820152601e60248201527f4174206c656173742074776f206f7574636f6d65732072657175697265640000604482015260640161076a565b600580545f91826118e18361216f565b909155505f8181526006602052604090209091508061190087826121d3565b5061190b8442612113565b600182015560028101805460ff191690555f1960038201555f5b8551811015611980575f838152600760205260409020865187908390811061194f5761194f61207c565b60209081029190910181015182546001810184555f93845291909220019061197790826121d3565b50600101611925565b50817fdb6ae5c511cd814e8b6d7dd1f64d32f3bd488e4361486cdcfa2e2debaeddca87878784600101546040516119b99392919061228e565b60405180910390a250949350505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a35050565b5f8281526002602090815260408083206001600160a01b038516845290915290205460ff16610b2e5760405163043c588360e11b81526001600160a01b03821660048201526024810183905260440161076a565b5f8281526002602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b611ad18282611a19565b5f8281526002602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b5f60048054611b3690612090565b80601f0160208091040260200160405190810160405280929190818152602001828054611b6290612090565b8015611bad5780601f10611b8457610100808354040283529160200191611bad565b820191905f5260205f20905b815481529060010190602001808311611b9057829003601f168201915b505050505090508160049081611bc391906121d3565b507fc9c7c3fe08b88b4df9d4d47ef47d2c43d55c025a0ba88ca442580ed9e7348a168183604051611bf59291906122c3565b60405180910390a15050565b5f60208284031215611c11575f80fd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f82825180855260208501945060208160051b830101602085015f5b83811015611c9457601f19858403018852611c7e838351611c18565b6020988901989093509190910190600101611c62565b50909695505050505050565b602081525f611cb26020830184611c46565b9392505050565b6001600160a01b0381168114610745575f80fd5b5f60208284031215611cdd575f80fd5b8135611cb281611cb9565b5f805f60408486031215611cfa575f80fd5b83359250602084013567ffffffffffffffff811115611d17575f80fd5b8401601f81018613611d27575f80fd5b803567ffffffffffffffff811115611d3d575f80fd5b8660208260051b8401011115611d51575f80fd5b939660209190910195509293505050565b5f8060408385031215611d73575f80fd5b823591506020830135611d8581611cb9565b809150509250929050565b5f8060408385031215611da1575f80fd5b50508035926020909101359150565b602081525f611cb26020830184611c18565b608081525f611dd46080830187611c18565b6020830195909552509115156040830152606090910152919050565b602080825282518282018190525f918401906040840190835b81811015611e27578351835260209384019390920191600101611e09565b509095945050505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611e6f57611e6f611e32565b604052919050565b5f82601f830112611e86575f80fd5b813567ffffffffffffffff811115611ea057611ea0611e32565b611eb3601f8201601f1916602001611e46565b818152846020838601011115611ec7575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60208284031215611ef3575f80fd5b813567ffffffffffffffff811115611f09575f80fd5b611f1584828501611e77565b949350505050565b5f805f60608486031215611f2f575f80fd5b833592506020840135611f4181611cb9565b929592945050506040919091013590565b5f8060408385031215611f63575f80fd5b8235611f6e81611cb9565b946020939093013593505050565b5f805f60608486031215611f8e575f80fd5b833567ffffffffffffffff811115611fa4575f80fd5b611fb086828701611e77565b935050602084013567ffffffffffffffff811115611fcc575f80fd5b8401601f81018613611fdc575f80fd5b803567ffffffffffffffff811115611ff657611ff6611e32565b8060051b61200660208201611e46565b91825260208184018101929081019089841115612021575f80fd5b6020850192505b8383101561206757823567ffffffffffffffff811115612046575f80fd5b6120558b602083890101611e77565b83525060209283019290910190612028565b96999698505050506040949094013593505050565b634e487b7160e01b5f52603260045260245ffd5b600181811c908216806120a457607f821691505b6020821081036120c257634e487b7160e01b5f52602260045260245ffd5b50919050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b808201808211156112c2576112c26120ff565b80820281158282048414176112c2576112c26120ff565b5f8261215757634e487b7160e01b5f52601260045260245ffd5b500490565b818103818111156112c2576112c26120ff565b5f60018201612180576121806120ff565b5060010190565b601f8211156121ce57805f5260205f20601f840160051c810160208510156121ac5750805b601f840160051c820191505b818110156121cb575f81556001016121b8565b50505b505050565b815167ffffffffffffffff8111156121ed576121ed611e32565b612201816121fb8454612090565b84612187565b6020601f821160018114612233575f831561221c5750848201515b5f19600385901b1c1916600184901b1784556121cb565b5f84815260208120601f198516915b828110156122625787850151825560209485019460019092019101612242565b508482101561227f57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b606081525f6122a06060830186611c18565b82810360208401526122b28186611c46565b915050826040830152949350505050565b604081525f6122d56040830185611c18565b82810360208401526122e78185611c18565b9594505050505056fea2646970667358221220ba074de1fa58c3a3fcf333722514af5d85c4a236760da3d21f43d0abcd15cb1e64736f6c634300081a0033

Deployed Bytecode Sourcemap

23757:11851:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33764:330;;;;;;;;;;-1:-1:-1;33764:330:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2120:182;;;;;;;;;;-1:-1:-1;2120:182:0;;;;;:::i;:::-;;:::i;:::-;;16092:122;;;;;;;;;;-1:-1:-1;16092:122:0;;;;;:::i;:::-;16160:7;16187:19;;;:13;:19;;;;;;;16092:122;;;;2173:25:1;;;2161:2;2146:18;16092:122:0;2027:177:1;24764:27:0;;;;;;;;;;;;;;;;31212:1560;;;;;;;;;;-1:-1:-1;31212:1560:0;;;;;:::i;:::-;;:::i;16619:285::-;;;;;;;;;;-1:-1:-1;16619:285:0;;;;;:::i;:::-;;:::i;17867:242::-;;;;;;;;;;-1:-1:-1;17867:242:0;;;;;:::i;:::-;;:::i;24181:49::-;;;;;;;;;;-1:-1:-1;24181:49:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;33125:479::-;;;;;;;;;;-1:-1:-1;33125:479:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;24312:75::-;;;;;;;;;;-1:-1:-1;24312:75:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;29021:538;;;;;;;;;;-1:-1:-1;29021:538:0;;;;;:::i;:::-;;:::i;24816:30::-;;;;;;;;;;;;;;;;29684:1350;;;;;;;;;;-1:-1:-1;29684:1350:0;;;;;:::i;:::-;;:::i;34837:187::-;;;;;;;;;;-1:-1:-1;34837:187:0;;;;;:::i;:::-;;:::i;34318:385::-;;;;;;;;;;-1:-1:-1;34318:385:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;24644:62::-;;;;;;;;;;-1:-1:-1;24644:62:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5671:14:1;;5664:22;5646:41;;5634:2;5619:18;24644:62:0;5506:187:1;1850:88:0;;;;;;;;;;-1:-1:-1;1897:7:0;1924:6;1850:88;;-1:-1:-1;;;;;1924:6:0;;;5844:51:1;;5832:2;5817:18;1850:88:0;5698:203:1;14643:133:0;;;;;;;;;;-1:-1:-1;14643:133:0;;;;;:::i;:::-;;:::i;21561:207::-;;;;;;;;;;-1:-1:-1;21561:207:0;;;;;:::i;:::-;;:::i;14046:49::-;;;;;;;;;;-1:-1:-1;14046:49:0;14091:4;14046:49;;15543:217;;;;;;;;;;-1:-1:-1;15543:217:0;;;;;:::i;:::-;;:::i;24470:94::-;;;;;;;;;;-1:-1:-1;24470:94:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35233:372;;;;;;;;;;-1:-1:-1;35233:372:0;;;;;:::i;:::-;;:::i;24069:41::-;;;;;;;;;;-1:-1:-1;24069:41:0;;;;;:::i;:::-;;:::i;27921:827::-;;;;;;:::i;:::-;;:::i;17285:174::-;;;;;;;;;;-1:-1:-1;17285:174:0;;;;;:::i;:::-;;:::i;21113:34::-;;;;;;;;;;;;;:::i;24036:26::-;;;;;;;;;;;;;;;;26820:883;;;;;;;;;;-1:-1:-1;26820:883:0;;;;;:::i;:::-;;:::i;33764:330::-;33860:20;33896:24;;;:13;:24;;;;;:31;33832:15;;33860:20;33883:45;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33860:68;;33944:9;33939:126;33963:24;;;;:13;:24;;;;;:31;33959:35;;33939:126;;;34026:24;;;;:13;:24;;;;;:27;;34051:1;;34026:27;;;;;;:::i;:::-;;;;;;;;34016:37;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:4;34021:1;34016:7;;;;;;;;:::i;:::-;;;;;;;;;;:37;33996:3;;33939:126;;;-1:-1:-1;34082:4:0;33764:330;-1:-1:-1;;33764:330:0:o;2120:182::-;26127:4;1924:6;-1:-1:-1;;;;;1924:6:0;26151:10;:21;2186:76;;2229:21;;-1:-1:-1;;;2229:21:0;;;;;;;;;;;2186:76;2272:22;2284:9;2272:11;:22::i;:::-;2120:182;:::o;31212:1560::-;22529:1;22845:7;;:19;22837:63;;;;-1:-1:-1;;;22837:63:0;;;;;;;:::i;:::-;;;;;;;;;22529:1;22978:7;:18;;;31344:21:::1;31368:18:::0;;;:7:::1;:18;::::0;;;;31405:15;;::::1;::::0;::::1;;31397:51;;;::::0;-1:-1:-1;;;31397:51:0;;10598:2:1;31397:51:0::1;::::0;::::1;10580:21:1::0;10637:2;10617:18;;;10610:30;10676:25;10656:18;;;10649:53;10719:18;;31397:51:0::1;10396:347:1::0;31397:51:0::1;31485:25;::::0;::::1;::::0;31461:21:::1;31545:31:::0;;;:20:::1;:31;::::0;;;;;;;:46;;;;;;;;;31655:24;;;:13:::1;:24:::0;;;;;:31;31545:46;;31461:21;;31697:177:::1;31721:11;31717:1;:15;31697:177;;;31763:13;31758:1;:18;31754:109;;31813:31;::::0;;;:20:::1;:31;::::0;;;;;;;:34;;;;;;;;;31797:50:::1;::::0;;::::1;:::i;:::-;;;31754:109;31734:3;;31697:177;;;-1:-1:-1::0;31886:19:0::1;31924:17:::0;;31920:101:::1;;31996:13:::0;31973:19:::1;:12:::0;31988:4:::1;31973:19;:::i;:::-;31972:37;;;;:::i;:::-;31958:51;;31920:101;32038:9;32033:732;32053:17:::0;;::::1;32033:732;;;32092:12;32107:6;;32114:1;32107:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;32135:21;::::0;;;:10:::1;:21;::::0;;;;;;;-1:-1:-1;;;;;32135:27:0;::::1;::::0;;;;;;;;32092:24;;-1:-1:-1;32135:27:0::1;;32131:76;;;32183:8;;;32131:76;32223:18;32244:30:::0;;;:19:::1;:30;::::0;;;;;;;-1:-1:-1;;;;;32244:36:0;::::1;::::0;;;;;;;:51;;;;;;;;;;32314:15;;;32310:64:::1;;32350:8;;;;32310:64;32390:16;32451:4;32423:24;32436:11:::0;32423:10;:24:::1;:::i;:::-;32422:33;;;;:::i;:::-;32409:46;::::0;:10;:46:::1;:::i;:::-;32390:65;;32500:4;32470:10;:21;32481:9;32470:21;;;;;;;;;;;:27;32492:4;-1:-1:-1::0;;;;;32470:27:0::1;-1:-1:-1::0;;;;;32470:27:0::1;;;;;;;;;;;;;:34;;;;;;;;;;;;;;;;;;32573:1;32519:19;:30;32539:9;32519:30;;;;;;;;;;;:36;32550:4;-1:-1:-1::0;;;;;32519:36:0::1;-1:-1:-1::0;;;;;32519:36:0::1;;;;;;;;;;;;:51;32556:13;32519:51;;;;;;;;;;;:55;;;;32592:12;32618:4;-1:-1:-1::0;;;;;32610:18:0::1;32636:8;32610:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32591:58;;;32672:7;32664:35;;;::::0;-1:-1:-1;;;32664:35:0;;11817:2:1;32664:35:0::1;::::0;::::1;11799:21:1::0;11856:2;11836:18;;;11829:30;-1:-1:-1;;;11875:18:1;;;11868:45;11930:18;;32664:35:0::1;11615:339:1::0;32664:35:0::1;32738:4;-1:-1:-1::0;;;;;32719:34:0::1;32727:9;32719:34;32744:8;32719:34;;;;2173:25:1::0;;2161:2;2146:18;;2027:177;32719:34:0::1;;;;;;;;32077:688;;;;32033:732;32072:3;;32033:732;;;-1:-1:-1::0;;22485:1:0;23157:22;;-1:-1:-1;;;;;;;;31212:1560:0:o;16619:285::-;16715:19;;;;:13;:19;;;;;;16704:43;;16736:10;16704;:43::i;:::-;16762:14;;;;:8;:14;;;;;;;;-1:-1:-1;;;;;16762:23:0;;;;;;;;;;;;16758:103;;;16809:40;;-1:-1:-1;;;16809:40:0;;-1:-1:-1;;;;;12151:32:1;;16809:40:0;;;12133:51:1;12200:18;;;12193:34;;;12106:18;;16809:40:0;11959:274:1;16758:103:0;16871:25;16882:4;16888:7;16871:10;:25::i;:::-;16619:285;;:::o;17867:242::-;17959:10;-1:-1:-1;;;;;17959:21:0;;;17955:110;;18004:49;;-1:-1:-1;;;18004:49:0;;18033:10;18004:49;;;12412:51:1;-1:-1:-1;;;;;12499:32:1;;12479:18;;;12472:60;12385:18;;18004:49:0;12238:300:1;17955:110:0;18075:26;18087:4;18093:7;18075:11;:26::i;24181:49::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;33125:479::-;33284:15;33420:18;;;:7;:18;;;;;33501:14;;;;33530:15;;;;33560:25;;;;33449:147;;33247:22;;33284:15;;;;;33420:18;;;;33501:14;;33530:15;;;33420:18;;33449:147;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33125:479;;;;;:::o;29021:538::-;1897:7;1924:6;-1:-1:-1;;;;;1924:6:0;29145:10;:21;29137:56;;;;-1:-1:-1;;;29137:56:0;;12745:2:1;29137:56:0;;;12727:21:1;12784:2;12764:18;;;12757:30;-1:-1:-1;;;12803:18:1;;;12796:52;12865:18;;29137:56:0;12543:346:1;29137:56:0;29204:21;29228:18;;;:7;:18;;;;;29266:15;;;;;;29265:16;29257:45;;;;-1:-1:-1;;;29257:45:0;;13096:2:1;29257:45:0;;;13078:21:1;13135:2;13115:18;;;13108:30;-1:-1:-1;;;13154:18:1;;;13147:46;13210:18;;29257:45:0;12894:340:1;29257:45:0;29343:24;;;;:13;:24;;;;;:31;29321:53;;29313:81;;;;-1:-1:-1;;;29313:81:0;;13441:2:1;29313:81:0;;;13423:21:1;13480:2;13460:18;;;13453:30;-1:-1:-1;;;13499:18:1;;;13492:45;13554:18;;29313:81:0;13239:339:1;29313:81:0;29407:25;;;:47;;;29465:15;;;:22;;-1:-1:-1;;29465:22:0;29483:4;29465:22;;;29505:46;;29520:9;;29505:46;;;;29435:19;2173:25:1;;2161:2;2146:18;;2027:177;29505:46:0;;;;;;;;29126:433;29021:538;;:::o;29684:1350::-;22529:1;22845:7;;:19;22837:63;;;;-1:-1:-1;;;22837:63:0;;;;;;;:::i;:::-;22529:1;22978:7;:18;;;29759:21:::1;29783:18:::0;;;:7:::1;:18;::::0;;;;29820:15;;::::1;::::0;::::1;;29812:47;;;::::0;-1:-1:-1;;;29812:47:0;;13785:2:1;29812:47:0::1;::::0;::::1;13767:21:1::0;13824:2;13804:18;;;13797:30;-1:-1:-1;;;13843:18:1;;;13836:49;13902:18;;29812:47:0::1;13583:343:1::0;29812:47:0::1;29879:21;::::0;;;:10:::1;:21;::::0;;;;;;;29901:10:::1;29879:33:::0;;;;;;;;::::1;;29878:34;29870:62;;;::::0;-1:-1:-1;;;29870:62:0;;14133:2:1;29870:62:0::1;::::0;::::1;14115:21:1::0;14172:2;14152:18;;;14145:30;-1:-1:-1;;;14191:18:1;;;14184:45;14246:18;;29870:62:0::1;13931:339:1::0;29870:62:0::1;29969:25;::::0;::::1;::::0;29945:21:::1;30026:30:::0;;;:19:::1;:30;::::0;;;;;;;30057:10:::1;30026:42:::0;;;;;;;:57;;;;;;;;;30102:14;30094:38:::1;;;::::0;-1:-1:-1;;;30094:38:0;;14477:2:1;30094:38:0::1;::::0;::::1;14459:21:1::0;14516:2;14496:18;;;14489:30;-1:-1:-1;;;14535:18:1;;;14528:41;14586:18;;30094:38:0::1;14275:335:1::0;30094:38:0::1;30145:21;30169:31:::0;;;:20:::1;:31;::::0;;;;;;;:46;;;;;;;;;30279:24;;;:13:::1;:24:::0;;;;;:31;30169:46;;30145:21;;30321:177:::1;30345:11;30341:1;:15;30321:177;;;30387:13;30382:1;:18;30378:109;;30437:31;::::0;;;:20:::1;:31;::::0;;;;;;;:34;;;;;;;;;30421:50:::1;::::0;;::::1;:::i;:::-;;;30378:109;30358:3;;30321:177;;;-1:-1:-1::0;30510:19:0::1;30548:17:::0;;30544:101:::1;;30620:13:::0;30597:19:::1;:12:::0;30612:4:::1;30597:19;:::i;:::-;30596:37;;;;:::i;:::-;30582:51;;30544:101;30655:16;30716:4;30688:24;30701:11:::0;30688:10;:24:::1;:::i;:::-;30687:33;;;;:::i;:::-;30674:46;::::0;:10;:46:::1;:::i;:::-;30793:1;30733:30:::0;;;:19:::1;:30;::::0;;;;;;;30764:10:::1;30733:42:::0;;;;;;;;;:57;;;;;;;;:61;;;30805:21;;;:10:::1;:21:::0;;;;;:33;;;;;;;;;:40;;-1:-1:-1;;30805:40:0::1;30841:4;30805:40;::::0;;30877:45;30655:65;;-1:-1:-1;30793:1:0;;30655:65;;30793:1;30877:45;30793:1;30877:45;30655:65;30764:10;30877:45:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30858:64;;;30941:7;30933:35;;;::::0;-1:-1:-1;;;30933:35:0;;11817:2:1;30933:35:0::1;::::0;::::1;11799:21:1::0;11856:2;11836:18;;;11829:30;-1:-1:-1;;;11875:18:1;;;11868:45;11930:18;;30933:35:0::1;11615:339:1::0;30933:35:0::1;30986:40;::::0;2173:25:1;;;31005:10:0::1;::::0;30994:9;;30986:40:::1;::::0;2161:2:1;2146:18;30986:40:0::1;;;;;;;-1:-1:-1::0;;22485:1:0;23157:22;;-1:-1:-1;;;;;;;;29684:1350:0:o;34837:187::-;1690:6;;-1:-1:-1;;;;;1690:6:0;1676:10;:20;1672:81;;1720:21;;-1:-1:-1;;;1720:21:0;;;;;;;;;;;1672:81;34922:4:::1;34911:7;:15;;34903:40;;;::::0;-1:-1:-1;;;34903:40:0;;14817:2:1;34903:40:0::1;::::0;::::1;14799:21:1::0;14856:2;14836:18;;;14829:30;-1:-1:-1;;;14875:18:1;;;14868:42;14927:18;;34903:40:0::1;14615:336:1::0;34903:40:0::1;34965:6;:16:::0;;;34997:19:::1;::::0;2173:25:1;;;34997:19:0::1;::::0;2161:2:1;2146:18;34997:19:0::1;;;;;;;34837:187:::0;:::o;34318:385::-;34461:19;34483:24;;;:13;:24;;;;;:31;34423:25;;34483:31;34536:26;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;34536:26:0;;34525:37;;34578:9;34573:123;34597:11;34593:1;:15;34573:123;;;34644:30;;;;:19;:30;;;;;;;;-1:-1:-1;;;;;34644:37:0;;;;;;;;;:40;;;;;;;;;34630:11;;:8;;34682:1;;34630:11;;;;;;:::i;:::-;;;;;;;;;;:54;34610:3;;34573:123;;;;34450:253;34318:385;;;;:::o;14643:133::-;14721:4;14745:14;;;:8;:14;;;;;;;;-1:-1:-1;;;;;14745:23:0;;;;;;;;;;;;14643:133;;;;;:::o;21561:207::-;26127:4;1924:6;-1:-1:-1;;;;;1924:6:0;26151:10;:21;21634:91;;21683:30;;-1:-1:-1;;;21683:30:0;;;;;;;;;;;21634:91;21737:23;21755:4;21737:17;:23::i;15543:217::-;15622:4;15644:14;;;:8;:14;;;;;;;;:26;;;;;;;;;;;15639:90;;-1:-1:-1;15694:14:0;;;;:8;:14;;;;;;;;-1:-1:-1;;;;;15694:23:0;;;;;;;;;;;;15687:30;;15639:90;-1:-1:-1;15748:4:0;15543:217;;;;:::o;35233:372::-;1690:6;;-1:-1:-1;;;;;1690:6:0;1676:10;:20;1672:81;;1720:21;;-1:-1:-1;;;1720:21:0;;;;;;;;;;;1672:81;22529:1:::1;22845:7;;:19:::0;22837:63:::1;;;;-1:-1:-1::0;;;22837:63:0::1;;;;;;;:::i;:::-;22529:1;22978:7;:18:::0;35362:15:::2;::::0;35351:26;::::2;;35343:54;;;::::0;-1:-1:-1;;;35343:54:0;;15158:2:1;35343:54:0::2;::::0;::::2;15140:21:1::0;15197:2;15177:18;;;15170:30;-1:-1:-1;;;15216:18:1;;;15209:45;15271:18;;35343:54:0::2;14956:339:1::0;35343:54:0::2;35427:7;35408:15;;:26;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;35464:35:0::2;::::0;35446:12:::2;::::0;-1:-1:-1;;;;;35464:15:0;::::2;::::0;35487:7;;35446:12;35464:35;35446:12;35464:35;35487:7;35464:15;:35:::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35445:54;;;35518:7;35510:35;;;::::0;-1:-1:-1;;;35510:35:0;;15635:2:1;35510:35:0::2;::::0;::::2;15617:21:1::0;15674:2;15654:18;;;15647:30;-1:-1:-1;;;15693:18:1;;;15686:45;15748:18;;35510:35:0::2;15433:339:1::0;35510:35:0::2;35586:10;-1:-1:-1::0;;;;;35563:34:0::2;;35577:7;35563:34;;;;2173:25:1::0;;2161:2;2146:18;;2027:177;35563:34:0::2;;;;;;;;-1:-1:-1::0;;22485:1:0::1;23157:22:::0;;-1:-1:-1;35233:372:0:o;24069:41::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;24069:41:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;24069:41:0;:::o;27921:827::-;28034:21;28058:18;;;:7;:18;;;;;28113:14;;;;28095:15;:32;28087:72;;;;-1:-1:-1;;;28087:72:0;;15979:2:1;28087:72:0;;;15961:21:1;16018:2;15998:18;;;15991:30;16057:29;16037:18;;;16030:57;16104:18;;28087:72:0;15777:351:1;28087:72:0;28179:15;;;;;;28178:16;28170:52;;;;-1:-1:-1;;;28170:52:0;;16335:2:1;28170:52:0;;;16317:21:1;16374:2;16354:18;;;16347:30;16413:25;16393:18;;;16386:53;16456:18;;28170:52:0;16133:347:1;28170:52:0;28256:24;;;;:13;:24;;;;;:31;28241:46;;28233:73;;;;-1:-1:-1;;;28233:73:0;;16687:2:1;28233:73:0;;;16669:21:1;16726:2;16706:18;;;16699:30;-1:-1:-1;;;16745:18:1;;;16738:44;16799:18;;28233:73:0;16485:338:1;28233:73:0;28337:1;28325:9;:13;28317:39;;;;-1:-1:-1;;;28317:39:0;;17030:2:1;28317:39:0;;;17012:21:1;17069:2;17049:18;;;17042:30;-1:-1:-1;;;17088:18:1;;;17081:43;17141:18;;28317:39:0;16828:337:1;28317:39:0;28369:17;28412:5;28402:6;;28390:9;:18;;;;:::i;:::-;28389:28;;;;:::i;:::-;28369:48;-1:-1:-1;28428:17:0;28448:21;28369:48;28448:9;:21;:::i;:::-;28428:41;;28501:9;28482:15;;:28;;;;;;;:::i;:::-;;;;-1:-1:-1;;28521:30:0;;;;:19;:30;;;;;;;;28552:10;28521:42;;;;;;;:56;;;;;;;;:69;;28581:9;;28521:30;:69;;28581:9;;28521:69;:::i;:::-;;;;-1:-1:-1;;28601:31:0;;;;:20;:31;;;;;;;;:45;;;;;;;;:58;;28650:9;;28601:31;:58;;28650:9;;28601:58;:::i;:::-;;;;-1:-1:-1;;28677:63:0;;;17344:25:1;;;17400:2;17385:18;;17378:34;;;28704:10:0;;28693:9;;28677:63;;17317:18:1;28677:63:0;;;;;;;28023:725;;;27921:827;;:::o;17285:174::-;17382:19;;;;:13;:19;;;;;;17371:43;;17403:10;17371;:43::i;21113:34::-;;;;;;;:::i;26820:883::-;26964:7;1924:6;;-1:-1:-1;;;;;1924:6:0;26992:10;:21;26984:63;;;;-1:-1:-1;;;26984:63:0;;17625:2:1;26984:63:0;;;17607:21:1;17664:2;17644:18;;;17637:30;17703:31;17683:18;;;17676:59;17752:18;;26984:63:0;17423:353:1;26984:63:0;27078:1;27066:9;:13;27058:51;;;;-1:-1:-1;;;27058:51:0;;17983:2:1;27058:51:0;;;17965:21:1;18022:2;18002:18;;;17995:30;18061:27;18041:18;;;18034:55;18106:18;;27058:51:0;17781:349:1;27058:51:0;27147:1;27128:8;:15;:20;;27120:63;;;;-1:-1:-1;;;27120:63:0;;18337:2:1;27120:63:0;;;18319:21:1;18376:2;18356:18;;;18349:30;18415:32;18395:18;;;18388:60;18465:18;;27120:63:0;18135:354:1;27120:63:0;27215:11;:13;;27196:16;;;27215:13;;;:::i;:::-;;;;-1:-1:-1;27239:21:0;27263:17;;;:7;:17;;;;;27196:32;;-1:-1:-1;27263:17:0;27293:27;27311:9;27263:17;27293:27;:::i;:::-;-1:-1:-1;27348:27:0;27366:9;27348:15;:27;:::i;:::-;27331:14;;;:44;27386:15;;;:23;;-1:-1:-1;;27386:23:0;;;-1:-1:-1;;27420:25:0;;;:45;27404:5;27478:114;27502:8;:15;27498:1;:19;27478:114;;;27539:23;;;;:13;:23;;;;;27568:11;;:8;;27577:1;;27568:11;;;;;;:::i;:::-;;;;;;;;;;;;27539:41;;;;;;;-1:-1:-1;27539:41:0;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;27519:3:0;;27478:114;;;;27623:8;27609:60;27633:9;27644:8;27654:6;:14;;;27609:60;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;27687:8:0;26820:883;-1:-1:-1;;;;26820:883:0:o;2420:177::-;2480:18;2501:6;;-1:-1:-1;;;;;2518:18:0;;;-1:-1:-1;;;;;;2518:18:0;;;;;;2554:35;;2501:6;;;;;;;2554:35;;2480:18;2554:35;2469:128;2420:177;:::o;19006:200::-;19095:14;;;;:8;:14;;;;;;;;-1:-1:-1;;;;;19095:23:0;;;;;;;;;;;;19090:109;;19142:45;;-1:-1:-1;;;19142:45:0;;-1:-1:-1;;;;;12151:32:1;;19142:45:0;;;12133:51:1;12200:18;;;12193:34;;;12106:18;;19142:45:0;11959:274:1;18472:171:0;18551:14;;;;:8;:14;;;;;;;;-1:-1:-1;;;;;18551:23:0;;;;;;;;;;:30;;-1:-1:-1;;18551:30:0;18577:4;18551:30;;;18597:38;18624:10;;18560:4;;18597:38;;18551:14;18597:38;18472:171;;:::o;18695:208::-;18775:25;18786:4;18792:7;18775:10;:25::i;:::-;18818:14;;;;:8;:14;;;;;;;;-1:-1:-1;;;;;18818:23:0;;;;;;;;;;18811:30;;-1:-1:-1;;18811:30:0;;;18857:38;18884:10;;18827:4;;18857:38;;18818:14;18857:38;18695:208;;:::o;21853:190::-;21920:21;21944:11;21920:35;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21980:4;21966:11;:18;;;;;;:::i;:::-;;22002:33;22021:7;22030:4;22002:33;;;;;;;:::i;:::-;;;;;;;;21909:134;21853:190;:::o;14:226:1:-;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;187:23:1;;14:226;-1:-1:-1;14:226:1:o;245:289::-;287:3;325:5;319:12;352:6;347:3;340:19;408:6;401:4;394:5;390:16;383:4;378:3;374:14;368:47;460:1;453:4;444:6;439:3;435:16;431:27;424:38;523:4;516:2;512:7;507:2;499:6;495:15;491:29;486:3;482:39;478:50;471:57;;;245:289;;;;:::o;539:579::-;591:3;622;654:5;648:12;681:6;676:3;669:19;713:4;708:3;704:14;697:21;;771:4;761:6;758:1;754:14;747:5;743:26;739:37;810:4;803:5;799:16;833:1;843:249;857:6;854:1;851:13;843:249;;;944:2;940:7;932:5;926:4;922:16;918:30;913:3;906:43;970:38;1003:4;994:6;988:13;970:38;:::i;:::-;1043:4;1068:14;;;;962:46;;-1:-1:-1;1031:17:1;;;;;879:1;872:9;843:249;;;-1:-1:-1;1108:4:1;;539:579;-1:-1:-1;;;;;;539:579:1:o;1123:280::-;1322:2;1311:9;1304:21;1285:4;1342:55;1393:2;1382:9;1378:18;1370:6;1342:55;:::i;:::-;1334:63;1123:280;-1:-1:-1;;;1123:280:1:o;1408:131::-;-1:-1:-1;;;;;1483:31:1;;1473:42;;1463:70;;1529:1;1526;1519:12;1544:247;1603:6;1656:2;1644:9;1635:7;1631:23;1627:32;1624:52;;;1672:1;1669;1662:12;1624:52;1711:9;1698:23;1730:31;1755:5;1730:31;:::i;2391:724::-;2486:6;2494;2502;2555:2;2543:9;2534:7;2530:23;2526:32;2523:52;;;2571:1;2568;2561:12;2523:52;2616:23;;;-1:-1:-1;2714:2:1;2699:18;;2686:32;2741:18;2730:30;;2727:50;;;2773:1;2770;2763:12;2727:50;2796:22;;2849:4;2841:13;;2837:27;-1:-1:-1;2827:55:1;;2878:1;2875;2868:12;2827:55;2918:2;2905:16;2944:18;2936:6;2933:30;2930:50;;;2976:1;2973;2966:12;2930:50;3029:7;3024:2;3014:6;3011:1;3007:14;3003:2;2999:23;2995:32;2992:45;2989:65;;;3050:1;3047;3040:12;2989:65;2391:724;;3081:2;3073:11;;;;;-1:-1:-1;3103:6:1;;-1:-1:-1;;;2391:724:1:o;3120:367::-;3188:6;3196;3249:2;3237:9;3228:7;3224:23;3220:32;3217:52;;;3265:1;3262;3255:12;3217:52;3310:23;;;-1:-1:-1;3409:2:1;3394:18;;3381:32;3422:33;3381:32;3422:33;:::i;:::-;3474:7;3464:17;;;3120:367;;;;;:::o;3492:346::-;3560:6;3568;3621:2;3609:9;3600:7;3596:23;3592:32;3589:52;;;3637:1;3634;3627:12;3589:52;-1:-1:-1;;3682:23:1;;;3802:2;3787:18;;;3774:32;;-1:-1:-1;3492:346:1:o;3843:220::-;3992:2;3981:9;3974:21;3955:4;4012:45;4053:2;4042:9;4038:18;4030:6;4012:45;:::i;4068:445::-;4295:3;4284:9;4277:22;4258:4;4316:46;4357:3;4346:9;4342:19;4334:6;4316:46;:::i;:::-;4393:2;4378:18;;4371:34;;;;-1:-1:-1;4448:14:1;;4441:22;4436:2;4421:18;;4414:50;4495:2;4480:18;;;4473:34;4308:54;4068:445;-1:-1:-1;4068:445:1:o;4890:611::-;5080:2;5092:21;;;5162:13;;5065:18;;;5184:22;;;5032:4;;5263:15;;;5237:2;5222:18;;;5032:4;5306:169;5320:6;5317:1;5314:13;5306:169;;;5381:13;;5369:26;;5424:2;5450:15;;;;5415:12;;;;5342:1;5335:9;5306:169;;;-1:-1:-1;5492:3:1;;4890:611;-1:-1:-1;;;;;4890:611:1:o;5906:127::-;5967:10;5962:3;5958:20;5955:1;5948:31;5998:4;5995:1;5988:15;6022:4;6019:1;6012:15;6038:275;6109:2;6103:9;6174:2;6155:13;;-1:-1:-1;;6151:27:1;6139:40;;6209:18;6194:34;;6230:22;;;6191:62;6188:88;;;6256:18;;:::i;:::-;6292:2;6285:22;6038:275;;-1:-1:-1;6038:275:1:o;6318:559::-;6361:5;6414:3;6407:4;6399:6;6395:17;6391:27;6381:55;;6432:1;6429;6422:12;6381:55;6472:6;6459:20;6502:18;6494:6;6491:30;6488:56;;;6524:18;;:::i;:::-;6568:59;6615:2;6592:17;;-1:-1:-1;;6588:31:1;6621:4;6584:42;6568:59;:::i;:::-;6652:6;6643:7;6636:23;6706:3;6699:4;6690:6;6682;6678:19;6674:30;6671:39;6668:59;;;6723:1;6720;6713:12;6668:59;6788:6;6781:4;6773:6;6769:17;6762:4;6753:7;6749:18;6736:59;6844:1;6815:20;;;6837:4;6811:31;6804:42;;;;6819:7;6318:559;-1:-1:-1;;;6318:559:1:o;6882:322::-;6951:6;7004:2;6992:9;6983:7;6979:23;6975:32;6972:52;;;7020:1;7017;7010:12;6972:52;7060:9;7047:23;7093:18;7085:6;7082:30;7079:50;;;7125:1;7122;7115:12;7079:50;7148;7190:7;7181:6;7170:9;7166:22;7148:50;:::i;:::-;7138:60;6882:322;-1:-1:-1;;;;6882:322:1:o;7209:487::-;7286:6;7294;7302;7355:2;7343:9;7334:7;7330:23;7326:32;7323:52;;;7371:1;7368;7361:12;7323:52;7416:23;;;-1:-1:-1;7515:2:1;7500:18;;7487:32;7528:33;7487:32;7528:33;:::i;:::-;7209:487;;7580:7;;-1:-1:-1;;;7660:2:1;7645:18;;;;7632:32;;7209:487::o;7701:375::-;7777:6;7785;7838:2;7826:9;7817:7;7813:23;7809:32;7806:52;;;7854:1;7851;7844:12;7806:52;7893:9;7880:23;7912:31;7937:5;7912:31;:::i;:::-;7962:5;8040:2;8025:18;;;;8012:32;;-1:-1:-1;;;7701:375:1:o;8081:1433::-;8203:6;8211;8219;8272:2;8260:9;8251:7;8247:23;8243:32;8240:52;;;8288:1;8285;8278:12;8240:52;8328:9;8315:23;8361:18;8353:6;8350:30;8347:50;;;8393:1;8390;8383:12;8347:50;8416;8458:7;8449:6;8438:9;8434:22;8416:50;:::i;:::-;8406:60;;;8519:2;8508:9;8504:18;8491:32;8548:18;8538:8;8535:32;8532:52;;;8580:1;8577;8570:12;8532:52;8603:24;;8658:4;8650:13;;8646:27;-1:-1:-1;8636:55:1;;8687:1;8684;8677:12;8636:55;8727:2;8714:16;8753:18;8745:6;8742:30;8739:56;;;8775:18;;:::i;:::-;8821:6;8818:1;8814:14;8848:28;8872:2;8868;8864:11;8848:28;:::i;:::-;8910:19;;;8954:2;8984:11;;;8980:20;;;8945:12;;;;9012:19;;;9009:39;;;9044:1;9041;9034:12;9009:39;9076:2;9072;9068:11;9057:22;;9088:299;9104:6;9099:3;9096:15;9088:299;;;9190:3;9177:17;9226:18;9213:11;9210:35;9207:55;;;9258:1;9255;9248:12;9207:55;9287:57;9336:7;9331:2;9317:11;9313:2;9309:20;9305:29;9287:57;:::i;:::-;9275:70;;-1:-1:-1;9374:2:1;9121:12;;;;9365;;;;9088:299;;;8081:1433;;9406:5;;-1:-1:-1;;;;9480:2:1;9465:18;;;;9452:32;;-1:-1:-1;;;8081:1433:1:o;9519:127::-;9580:10;9575:3;9571:20;9568:1;9561:31;9611:4;9608:1;9601:15;9635:4;9632:1;9625:15;9651:380;9730:1;9726:12;;;;9773;;;9794:61;;9848:4;9840:6;9836:17;9826:27;;9794:61;9901:2;9893:6;9890:14;9870:18;9867:38;9864:161;;9947:10;9942:3;9938:20;9935:1;9928:31;9982:4;9979:1;9972:15;10010:4;10007:1;10000:15;9864:161;;9651:380;;;:::o;10036:355::-;10238:2;10220:21;;;10277:2;10257:18;;;10250:30;10316:33;10311:2;10296:18;;10289:61;10382:2;10367:18;;10036:355::o;10748:127::-;10809:10;10804:3;10800:20;10797:1;10790:31;10840:4;10837:1;10830:15;10864:4;10861:1;10854:15;10880:125;10945:9;;;10966:10;;;10963:36;;;10979:18;;:::i;11010:168::-;11083:9;;;11114;;11131:15;;;11125:22;;11111:37;11101:71;;11152:18;;:::i;11183:217::-;11223:1;11249;11239:132;;11293:10;11288:3;11284:20;11281:1;11274:31;11328:4;11325:1;11318:15;11356:4;11353:1;11346:15;11239:132;-1:-1:-1;11385:9:1;;11183:217::o;15300:128::-;15367:9;;;15388:11;;;15385:37;;;15402:18;;:::i;18494:135::-;18533:3;18554:17;;;18551:43;;18574:18;;:::i;:::-;-1:-1:-1;18621:1:1;18610:13;;18494:135::o;18760:518::-;18862:2;18857:3;18854:11;18851:421;;;18898:5;18895:1;18888:16;18942:4;18939:1;18929:18;19012:2;19000:10;18996:19;18993:1;18989:27;18983:4;18979:38;19048:4;19036:10;19033:20;19030:47;;;-1:-1:-1;19071:4:1;19030:47;19126:2;19121:3;19117:12;19114:1;19110:20;19104:4;19100:31;19090:41;;19181:81;19199:2;19192:5;19189:13;19181:81;;;19258:1;19244:16;;19225:1;19214:13;19181:81;;;19185:3;;18851:421;18760:518;;;:::o;19454:1299::-;19580:3;19574:10;19607:18;19599:6;19596:30;19593:56;;;19629:18;;:::i;:::-;19658:97;19748:6;19708:38;19740:4;19734:11;19708:38;:::i;:::-;19702:4;19658:97;:::i;:::-;19804:4;19835:2;19824:14;;19852:1;19847:649;;;;20540:1;20557:6;20554:89;;;-1:-1:-1;20609:19:1;;;20603:26;20554:89;-1:-1:-1;;19411:1:1;19407:11;;;19403:24;19399:29;19389:40;19435:1;19431:11;;;19386:57;20656:81;;19817:930;;19847:649;18707:1;18700:14;;;18744:4;18731:18;;-1:-1:-1;;19883:20:1;;;20001:222;20015:7;20012:1;20009:14;20001:222;;;20097:19;;;20091:26;20076:42;;20204:4;20189:20;;;;20157:1;20145:14;;;;20031:12;20001:222;;;20005:3;20251:6;20242:7;20239:19;20236:201;;;20312:19;;;20306:26;-1:-1:-1;;20395:1:1;20391:14;;;20407:3;20387:24;20383:37;20379:42;20364:58;20349:74;;20236:201;-1:-1:-1;;;;20483:1:1;20467:14;;;20463:22;20450:36;;-1:-1:-1;19454:1299:1:o;20758:514::-;21033:2;21022:9;21015:21;20996:4;21059:45;21100:2;21089:9;21085:18;21077:6;21059:45;:::i;:::-;21152:9;21144:6;21140:22;21135:2;21124:9;21120:18;21113:50;21180:43;21216:6;21208;21180:43;:::i;:::-;21172:51;;;21259:6;21254:2;21243:9;21239:18;21232:34;20758:514;;;;;;:::o;21277:383::-;21474:2;21463:9;21456:21;21437:4;21500:45;21541:2;21530:9;21526:18;21518:6;21500:45;:::i;:::-;21593:9;21585:6;21581:22;21576:2;21565:9;21561:18;21554:50;21621:33;21647:6;21639;21621:33;:::i;:::-;21613:41;21277:383;-1:-1:-1;;;;;21277:383:1:o

Swarm Source

ipfs://ba074de1fa58c3a3fcf333722514af5d85c4a236760da3d21f43d0abcd15cb1e

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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