ETH Price: $3,447.33 (-0.31%)
Gas: 17 Gwei

AEB BEGINS (AEB)
 

Overview

TokenID

1705

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
AEBBEGINS

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2023-08-04
*/

/**
 *Submitted for verification at Etherscan.io on 2023-02-25
*/

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;


library Bytecode {
  error InvalidCodeAtRange(uint256 _size, uint256 _start, uint256 _end);

  /**
    @notice Generate a creation code that results on a contract with `_code` as bytecode
    @param _code The returning value of the resulting `creationCode`
    @return creationCode (constructor) for new contract
  */
  function creationCodeFor(bytes memory _code) internal pure returns (bytes memory) {
    /*
      0x00    0x63         0x63XXXXXX  PUSH4 _code.length  size
      0x01    0x80         0x80        DUP1                size size
      0x02    0x60         0x600e      PUSH1 14            14 size size
      0x03    0x60         0x6000      PUSH1 00            0 14 size size
      0x04    0x39         0x39        CODECOPY            size
      0x05    0x60         0x6000      PUSH1 00            0 size
      0x06    0xf3         0xf3        RETURN
      <CODE>
    */

    return abi.encodePacked(
      hex"63",
      uint32(_code.length),
      hex"80_60_0E_60_00_39_60_00_F3",
      _code
    );
  }

  /**
    @notice Returns the size of the code on a given address
    @param _addr Address that may or may not contain code
    @return size of the code on the given `_addr`
  */
  function codeSize(address _addr) internal view returns (uint256 size) {
    assembly { size := extcodesize(_addr) }
  }

  /**
    @notice Returns the code of a given address
    @dev It will fail if `_end < _start`
    @param _addr Address that may or may not contain code
    @param _start number of bytes of code to skip on read
    @param _end index before which to end extraction
    @return oCode read from `_addr` deployed bytecode

    Forked from: https://gist.github.com/KardanovIR/fe98661df9338c842b4a30306d507fbd
  */
  function codeAt(address _addr, uint256 _start, uint256 _end) internal view returns (bytes memory oCode) {
    uint256 csize = codeSize(_addr);
    if (csize == 0) return bytes("");

    if (_start > csize) return bytes("");
    if (_end < _start) revert InvalidCodeAtRange(csize, _start, _end); 

    unchecked {
      uint256 reqSize = _end - _start;
      uint256 maxSize = csize - _start;

      uint256 size = maxSize < reqSize ? maxSize : reqSize;

      assembly {
        // allocate output byte array - this could also be done without assembly
        // by using o_code = new bytes(size)
        oCode := mload(0x40)
        // new "memory end" including padding
        mstore(0x40, add(oCode, and(add(add(size, 0x20), 0x1f), not(0x1f))))
        // store length in memory
        mstore(oCode, size)
        // actually retrieve the code, this needs assembly
        extcodecopy(_addr, add(oCode, 0x20), _start, size)
      }
    }
  }
}
pragma solidity ^0.8.0;

/**
  @title A key-value storage with auto-generated keys for storing chunks of data with a lower write & read cost.
  @author Agustin Aguilar <[email protected]>
  Readme: https://github.com/0xsequence/sstore2#readme
*/
library SSTORE2 {
  error WriteError();

  /**
    @notice Stores `_data` and returns `pointer` as key for later retrieval
    @dev The pointer is a contract address with `_data` as code
    @param _data to be written
    @return pointer Pointer to the written `_data`
  */
  function write(bytes memory _data) internal returns (address pointer) {
    // Append 00 to _data so contract can't be called
    // Build init code
    bytes memory code = Bytecode.creationCodeFor(
      abi.encodePacked(
        hex'00',
        _data
      )
    );

    // Deploy contract using create
    assembly { pointer := create(0, add(code, 32), mload(code)) }

    // Address MUST be non-zero
    if (pointer == address(0)) revert WriteError();
  }

  /**
    @notice Reads the contents of the `_pointer` code as data, skips the first byte 
    @dev The function is intended for reading pointers generated by `write`
    @param _pointer to be read
    @return data read from `_pointer` contract
  */
  function read(address _pointer) internal view returns (bytes memory) {
    return Bytecode.codeAt(_pointer, 1, type(uint256).max);
  }

  /**
    @notice Reads the contents of the `_pointer` code as data, skips the first byte 
    @dev The function is intended for reading pointers generated by `write`
    @param _pointer to be read
    @param _start number of bytes to skip
    @return data read from `_pointer` contract
  */
  function read(address _pointer, uint256 _start) internal view returns (bytes memory) {
    return Bytecode.codeAt(_pointer, _start + 1, type(uint256).max);
  }

  /**
    @notice Reads the contents of the `_pointer` code as data, skips the first byte 
    @dev The function is intended for reading pointers generated by `write`
    @param _pointer to be read
    @param _start number of bytes to skip
    @param _end index before which to end extraction
    @return data read from `_pointer` contract
  */
  function read(address _pointer, uint256 _start, uint256 _end) internal view returns (bytes memory) {
    return Bytecode.codeAt(_pointer, _start + 1, _end + 1);
  }
}

pragma solidity >=0.8.0 <0.9.0;


library BytesLib {
    function concat(
        bytes memory _preBytes,
        bytes memory _postBytes
    )
        internal
        pure
        returns (bytes memory)
    {
        bytes memory tempBytes;

        assembly {
            // Get a location of some free memory and store it in tempBytes as
            // Solidity does for memory variables.
            tempBytes := mload(0x40)

            // Store the length of the first bytes array at the beginning of
            // the memory for tempBytes.
            let length := mload(_preBytes)
            mstore(tempBytes, length)

            // Maintain a memory counter for the current write location in the
            // temp bytes array by adding the 32 bytes for the array length to
            // the starting location.
            let mc := add(tempBytes, 0x20)
            // Stop copying when the memory counter reaches the length of the
            // first bytes array.
            let end := add(mc, length)

            for {
                // Initialize a copy counter to the start of the _preBytes data,
                // 32 bytes into its memory.
                let cc := add(_preBytes, 0x20)
            } lt(mc, end) {
                // Increase both counters by 32 bytes each iteration.
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                // Write the _preBytes data into the tempBytes memory 32 bytes
                // at a time.
                mstore(mc, mload(cc))
            }

            // Add the length of _postBytes to the current length of tempBytes
            // and store it as the new length in the first 32 bytes of the
            // tempBytes memory.
            length := mload(_postBytes)
            mstore(tempBytes, add(length, mload(tempBytes)))

            // Move the memory counter back from a multiple of 0x20 to the
            // actual end of the _preBytes data.
            mc := end
            // Stop copying when the memory counter reaches the new combined
            // length of the arrays.
            end := add(mc, length)

            for {
                let cc := add(_postBytes, 0x20)
            } lt(mc, end) {
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                mstore(mc, mload(cc))
            }

            // Update the free-memory pointer by padding our last write location
            // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
            // next 32 byte block, then round down to the nearest multiple of
            // 32. If the sum of the length of the two arrays is zero then add
            // one before rounding down to leave a blank 32 bytes (the length block with 0).
            mstore(0x40, and(
              add(add(end, iszero(add(length, mload(_preBytes)))), 31),
              not(31) // Round down to the nearest 32 bytes.
            ))
        }

        return tempBytes;
    }

    function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
        assembly {
            // Read the first 32 bytes of _preBytes storage, which is the length
            // of the array. (We don't need to use the offset into the slot
            // because arrays use the entire slot.)
            let fslot := sload(_preBytes.slot)
            // Arrays of 31 bytes or less have an even value in their slot,
            // while longer arrays have an odd value. The actual length is
            // the slot divided by two for odd values, and the lowest order
            // byte divided by two for even values.
            // If the slot is even, bitwise and the slot with 255 and divide by
            // two to get the length. If the slot is odd, bitwise and the slot
            // with -1 and divide by two.
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)
            let newlength := add(slength, mlength)
            // slength can contain both the length and contents of the array
            // if length < 32 bytes so let's prepare for that
            // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
            switch add(lt(slength, 32), lt(newlength, 32))
            case 2 {
                // Since the new array still fits in the slot, we just need to
                // update the contents of the slot.
                // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
                sstore(
                    _preBytes.slot,
                    // all the modifications to the slot are inside this
                    // next block
                    add(
                        // we can just add to the slot contents because the
                        // bytes we want to change are the LSBs
                        fslot,
                        add(
                            mul(
                                div(
                                    // load the bytes from memory
                                    mload(add(_postBytes, 0x20)),
                                    // zero all bytes to the right
                                    exp(0x100, sub(32, mlength))
                                ),
                                // and now shift left the number of bytes to
                                // leave space for the length in the slot
                                exp(0x100, sub(32, newlength))
                            ),
                            // increase length by the double of the memory
                            // bytes length
                            mul(mlength, 2)
                        )
                    )
                )
            }
            case 1 {
                // The stored value fits in the slot, but the combined value
                // will exceed it.
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes.slot)
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes.slot, add(mul(newlength, 2), 1))

                // The contents of the _postBytes array start 32 bytes into
                // the structure. Our first read should obtain the `submod`
                // bytes that can fit into the unused space in the last word
                // of the stored array. To get this, we read 32 bytes starting
                // from `submod`, so the data we read overlaps with the array
                // contents by `submod` bytes. Masking the lowest-order
                // `submod` bytes allows us to add that value directly to the
                // stored value.

                let submod := sub(32, slength)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(
                    sc,
                    add(
                        and(
                            fslot,
                            0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
                        ),
                        and(mload(mc), mask)
                    )
                )

                for {
                    mc := add(mc, 0x20)
                    sc := add(sc, 1)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
            default {
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes.slot)
                // Start copying to the last used word of the stored array.
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes.slot, add(mul(newlength, 2), 1))

                // Copy over the first `submod` bytes of the new data as in
                // case 1 above.
                let slengthmod := mod(slength, 32)
                let mlengthmod := mod(mlength, 32)
                let submod := sub(32, slengthmod)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(sc, add(sload(sc), and(mload(mc), mask)))

                for {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
        }
    }

    function slice(
        bytes memory _bytes,
        uint256 _start,
        uint256 _length
    )
        internal
        pure
        returns (bytes memory)
    {
        require(_length + 31 >= _length, "slice_overflow");
        require(_bytes.length >= _start + _length, "slice_outOfBounds");

        bytes memory tempBytes;

        assembly {
            switch iszero(_length)
            case 0 {
                // Get a location of some free memory and store it in tempBytes as
                // Solidity does for memory variables.
                tempBytes := mload(0x40)

                // The first word of the slice result is potentially a partial
                // word read from the original array. To read it, we calculate
                // the length of that partial word and start copying that many
                // bytes into the array. The first word we copy will start with
                // data we don't care about, but the last `lengthmod` bytes will
                // land at the beginning of the contents of the new array. When
                // we're done copying, we overwrite the full first word with
                // the actual length of the slice.
                let lengthmod := and(_length, 31)

                // The multiplication in the next line is necessary
                // because when slicing multiples of 32 bytes (lengthmod == 0)
                // the following copy loop was copying the origin's length
                // and then ending prematurely not copying everything it should.
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                    // The multiplication in the next line has the same exact purpose
                    // as the one above.
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    mstore(mc, mload(cc))
                }

                mstore(tempBytes, _length)

                //update free-memory pointer
                //allocating the array padded to 32 bytes like the compiler does now
                mstore(0x40, and(add(mc, 31), not(31)))
            }
            //if we want a zero-length slice let's just return a zero-length array
            default {
                tempBytes := mload(0x40)
                //zero out the 32 bytes slice we are about to return
                //we need to do it because Solidity does not garbage collect
                mstore(tempBytes, 0)

                mstore(0x40, add(tempBytes, 0x20))
            }
        }

        return tempBytes;
    }

    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
        require(_bytes.length >= _start + 20, "toAddress_outOfBounds");
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
        }

        return tempAddress;
    }

    function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
        require(_bytes.length >= _start + 1 , "toUint8_outOfBounds");
        uint8 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x1), _start))
        }

        return tempUint;
    }

    function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
        require(_bytes.length >= _start + 2, "toUint16_outOfBounds");
        uint16 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x2), _start))
        }

        return tempUint;
    }

    function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
        require(_bytes.length >= _start + 4, "toUint32_outOfBounds");
        uint32 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x4), _start))
        }

        return tempUint;
    }

    function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
        require(_bytes.length >= _start + 8, "toUint64_outOfBounds");
        uint64 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x8), _start))
        }

        return tempUint;
    }

    function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
        require(_bytes.length >= _start + 12, "toUint96_outOfBounds");
        uint96 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0xc), _start))
        }

        return tempUint;
    }

    function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
        require(_bytes.length >= _start + 16, "toUint128_outOfBounds");
        uint128 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x10), _start))
        }

        return tempUint;
    }

    function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
        require(_bytes.length >= _start + 32, "toUint256_outOfBounds");
        uint256 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x20), _start))
        }

        return tempUint;
    }

    function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
        require(_bytes.length >= _start + 32, "toBytes32_outOfBounds");
        bytes32 tempBytes32;

        assembly {
            tempBytes32 := mload(add(add(_bytes, 0x20), _start))
        }

        return tempBytes32;
    }

    function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
        bool success = true;

        assembly {
            let length := mload(_preBytes)

            // if lengths don't match the arrays are not equal
            switch eq(length, mload(_postBytes))
            case 1 {
                // cb is a circuit breaker in the for loop since there's
                //  no said feature for inline assembly loops
                // cb = 1 - don't breaker
                // cb = 0 - break
                let cb := 1

                let mc := add(_preBytes, 0x20)
                let end := add(mc, length)

                for {
                    let cc := add(_postBytes, 0x20)
                // the next line is the loop condition:
                // while(uint256(mc < end) + cb == 2)
                } eq(add(lt(mc, end), cb), 2) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    // if any of these checks fails then arrays are not equal
                    if iszero(eq(mload(mc), mload(cc))) {
                        // unsuccess:
                        success := 0
                        cb := 0
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }

    function equalStorage(
        bytes storage _preBytes,
        bytes memory _postBytes
    )
        internal
        view
        returns (bool)
    {
        bool success = true;

        assembly {
            // we know _preBytes_offset is 0
            let fslot := sload(_preBytes.slot)
            // Decode the length of the stored array like in concatStorage().
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)

            // if lengths don't match the arrays are not equal
            switch eq(slength, mlength)
            case 1 {
                // slength can contain both the length and contents of the array
                // if length < 32 bytes so let's prepare for that
                // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
                if iszero(iszero(slength)) {
                    switch lt(slength, 32)
                    case 1 {
                        // blank the last byte which is the length
                        fslot := mul(div(fslot, 0x100), 0x100)

                        if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
                            // unsuccess:
                            success := 0
                        }
                    }
                    default {
                        // cb is a circuit breaker in the for loop since there's
                        //  no said feature for inline assembly loops
                        // cb = 1 - don't breaker
                        // cb = 0 - break
                        let cb := 1

                        // get the keccak hash to get the contents of the array
                        mstore(0x0, _preBytes.slot)
                        let sc := keccak256(0x0, 0x20)

                        let mc := add(_postBytes, 0x20)
                        let end := add(mc, mlength)

                        // the next line is the loop condition:
                        // while(uint256(mc < end) + cb == 2)
                        for {} eq(add(lt(mc, end), cb), 2) {
                            sc := add(sc, 1)
                            mc := add(mc, 0x20)
                        } {
                            if iszero(eq(sload(sc), mload(mc))) {
                                // unsuccess:
                                success := 0
                                cb := 0
                            }
                        }
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }
}



/**
 *Submitted for verification at Etherscan.io on 2023-02-17
*/

// File: @openzeppelin/contracts/utils/structs/EnumerableSet.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastValue;
                // Update the index for the moved value
                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

// File: @openzeppelin/contracts/utils/StorageSlot.sol


// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }
}

// File: @openzeppelin/contracts/utils/Address.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

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

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

// File: @openzeppelin/contracts/utils/math/Math.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}

// File: @openzeppelin/contracts/utils/Strings.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)

pragma solidity ^0.8.0;


/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @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] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

// File: solidity-bits/contracts/Popcount.sol


/**
   _____       ___     ___ __           ____  _ __      
  / ___/____  / (_)___/ (_) /___  __   / __ )(_) /______
  \__ \/ __ \/ / / __  / / __/ / / /  / __  / / __/ ___/
 ___/ / /_/ / / / /_/ / / /_/ /_/ /  / /_/ / / /_(__  ) 
/____/\____/_/_/\__,_/_/\__/\__, /  /_____/_/\__/____/  
                           /____/                        

- npm: https://www.npmjs.com/package/solidity-bits
- github: https://github.com/estarriolvetch/solidity-bits

 */

pragma solidity ^0.8.0;

library Popcount {
    uint256 private constant m1 = 0x5555555555555555555555555555555555555555555555555555555555555555;
    uint256 private constant m2 = 0x3333333333333333333333333333333333333333333333333333333333333333;
    uint256 private constant m4 = 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f;
    uint256 private constant h01 = 0x0101010101010101010101010101010101010101010101010101010101010101;

    function popcount256A(uint256 x) internal pure returns (uint256 count) {
        unchecked{
            for (count=0; x!=0; count++)
                x &= x - 1;
        }
    }

    function popcount256B(uint256 x) internal pure returns (uint256) {
        if (x == type(uint256).max) {
            return 256;
        }
        unchecked {
            x -= (x >> 1) & m1;             //put count of each 2 bits into those 2 bits
            x = (x & m2) + ((x >> 2) & m2); //put count of each 4 bits into those 4 bits 
            x = (x + (x >> 4)) & m4;        //put count of each 8 bits into those 8 bits 
            x = (x * h01) >> 248;  //returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ... 
        }
        return x;
    }
}
// File: solidity-bits/contracts/BitScan.sol


/**
   _____       ___     ___ __           ____  _ __      
  / ___/____  / (_)___/ (_) /___  __   / __ )(_) /______
  \__ \/ __ \/ / / __  / / __/ / / /  / __  / / __/ ___/
 ___/ / /_/ / / / /_/ / / /_/ /_/ /  / /_/ / / /_(__  ) 
/____/\____/_/_/\__,_/_/\__/\__, /  /_____/_/\__/____/  
                           /____/                        

- npm: https://www.npmjs.com/package/solidity-bits
- github: https://github.com/estarriolvetch/solidity-bits

 */

pragma solidity ^0.8.0;


library BitScan {
    uint256 constant private DEBRUIJN_256 = 0x818283848586878898a8b8c8d8e8f929395969799a9b9d9e9faaeb6bedeeff;
    bytes constant private LOOKUP_TABLE_256 = hex"0001020903110a19042112290b311a3905412245134d2a550c5d32651b6d3a7506264262237d468514804e8d2b95569d0d495ea533a966b11c886eb93bc176c9071727374353637324837e9b47af86c7155181ad4fd18ed32c9096db57d59ee30e2e4a6a5f92a6be3498aae067ddb2eb1d5989b56fd7baf33ca0c2ee77e5caf7ff0810182028303840444c545c646c7425617c847f8c949c48a4a8b087b8c0c816365272829aaec650acd0d28fdad4e22d6991bd97dfdcea58b4d6f29fede4f6fe0f1f2f3f4b5b6b607b8b93a3a7b7bf357199c5abcfd9e168bcdee9b3f1ecf5fd1e3e5a7a8aa2b670c4ced8bbe8f0f4fc3d79a1c3cde7effb78cce6facbf9f8";

    /**
        @dev Isolate the least significant set bit.
     */ 
    function isolateLS1B256(uint256 bb) pure internal returns (uint256) {
        require(bb > 0);
        unchecked {
            return bb & (0 - bb);
        }
    } 

    /**
        @dev Isolate the most significant set bit.
     */ 
    function isolateMS1B256(uint256 bb) pure internal returns (uint256) {
        require(bb > 0);
        unchecked {
            bb |= bb >> 128;
            bb |= bb >> 64;
            bb |= bb >> 32;
            bb |= bb >> 16;
            bb |= bb >> 8;
            bb |= bb >> 4;
            bb |= bb >> 2;
            bb |= bb >> 1;
            
            return (bb >> 1) + 1;
        }
    } 

    /**
        @dev Find the index of the lest significant set bit. (trailing zero count)
     */ 
    function bitScanForward256(uint256 bb) pure internal returns (uint8) {
        unchecked {
            return uint8(LOOKUP_TABLE_256[(isolateLS1B256(bb) * DEBRUIJN_256) >> 248]);
        }   
    }

    /**
        @dev Find the index of the most significant set bit.
     */ 
    function bitScanReverse256(uint256 bb) pure internal returns (uint8) {
        unchecked {
            return 255 - uint8(LOOKUP_TABLE_256[((isolateMS1B256(bb) * DEBRUIJN_256) >> 248)]);
        }   
    }

    function log2(uint256 bb) pure internal returns (uint8) {
        unchecked {
            return uint8(LOOKUP_TABLE_256[(isolateMS1B256(bb) * DEBRUIJN_256) >> 248]);
        } 
    }
}

// File: solidity-bits/contracts/BitMaps.sol


/**
   _____       ___     ___ __           ____  _ __      
  / ___/____  / (_)___/ (_) /___  __   / __ )(_) /______
  \__ \/ __ \/ / / __  / / __/ / / /  / __  / / __/ ___/
 ___/ / /_/ / / / /_/ / / /_/ /_/ /  / /_/ / / /_(__  ) 
/____/\____/_/_/\__,_/_/\__/\__, /  /_____/_/\__/____/  
                           /____/                        

- npm: https://www.npmjs.com/package/solidity-bits
- github: https://github.com/estarriolvetch/solidity-bits

 */
pragma solidity ^0.8.0;



/**
 * @dev This Library is a modified version of Openzeppelin's BitMaps library with extra features.
 *
 * 1. Functions of finding the index of the closest set bit from a given index are added.
 *    The indexing of each bucket is modifed to count from the MSB to the LSB instead of from the LSB to the MSB.
 *    The modification of indexing makes finding the closest previous set bit more efficient in gas usage.
 * 2. Setting and unsetting the bitmap consecutively.
 * 3. Accounting number of set bits within a given range.   
 *
*/

/**
 * @dev Library for managing uint256 to bool mapping in a compact and efficient way, providing the keys are sequential.
 * Largelly inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor].
 */

library BitMaps {
    using BitScan for uint256;
    uint256 private constant MASK_INDEX_ZERO = (1 << 255);
    uint256 private constant MASK_FULL = type(uint256).max;

    struct BitMap {
        mapping(uint256 => uint256) _data;
    }

    /**
     * @dev Returns whether the bit at `index` is set.
     */
    function get(BitMap storage bitmap, uint256 index) internal view returns (bool) {
        uint256 bucket = index >> 8;
        uint256 mask = MASK_INDEX_ZERO >> (index & 0xff);
        return bitmap._data[bucket] & mask != 0;
    }

    /**
     * @dev Sets the bit at `index` to the boolean `value`.
     */
    function setTo(
        BitMap storage bitmap,
        uint256 index,
        bool value
    ) internal {
        if (value) {
            set(bitmap, index);
        } else {
            unset(bitmap, index);
        }
    }

    /**
     * @dev Sets the bit at `index`.
     */
    function set(BitMap storage bitmap, uint256 index) internal {
        uint256 bucket = index >> 8;
        uint256 mask = MASK_INDEX_ZERO >> (index & 0xff);
        bitmap._data[bucket] |= mask;
    }

    /**
     * @dev Unsets the bit at `index`.
     */
    function unset(BitMap storage bitmap, uint256 index) internal {
        uint256 bucket = index >> 8;
        uint256 mask = MASK_INDEX_ZERO >> (index & 0xff);
        bitmap._data[bucket] &= ~mask;
    }


    /**
     * @dev Consecutively sets `amount` of bits starting from the bit at `startIndex`.
     */    
    function setBatch(BitMap storage bitmap, uint256 startIndex, uint256 amount) internal {
        uint256 bucket = startIndex >> 8;

        uint256 bucketStartIndex = (startIndex & 0xff);

        unchecked {
            if(bucketStartIndex + amount < 256) {
                bitmap._data[bucket] |= MASK_FULL << (256 - amount) >> bucketStartIndex;
            } else {
                bitmap._data[bucket] |= MASK_FULL >> bucketStartIndex;
                amount -= (256 - bucketStartIndex);
                bucket++;

                while(amount > 256) {
                    bitmap._data[bucket] = MASK_FULL;
                    amount -= 256;
                    bucket++;
                }

                bitmap._data[bucket] |= MASK_FULL << (256 - amount);
            }
        }
    }


    /**
     * @dev Consecutively unsets `amount` of bits starting from the bit at `startIndex`.
     */    
    function unsetBatch(BitMap storage bitmap, uint256 startIndex, uint256 amount) internal {
        uint256 bucket = startIndex >> 8;

        uint256 bucketStartIndex = (startIndex & 0xff);

        unchecked {
            if(bucketStartIndex + amount < 256) {
                bitmap._data[bucket] &= ~(MASK_FULL << (256 - amount) >> bucketStartIndex);
            } else {
                bitmap._data[bucket] &= ~(MASK_FULL >> bucketStartIndex);
                amount -= (256 - bucketStartIndex);
                bucket++;

                while(amount > 256) {
                    bitmap._data[bucket] = 0;
                    amount -= 256;
                    bucket++;
                }

                bitmap._data[bucket] &= ~(MASK_FULL << (256 - amount));
            }
        }
    }

    /**
     * @dev Returns number of set bits within a range.
     */
    function popcountA(BitMap storage bitmap, uint256 startIndex, uint256 amount) internal view returns(uint256 count) {
        uint256 bucket = startIndex >> 8;

        uint256 bucketStartIndex = (startIndex & 0xff);

        unchecked {
            if(bucketStartIndex + amount < 256) {
                count +=  Popcount.popcount256A(
                    bitmap._data[bucket] & (MASK_FULL << (256 - amount) >> bucketStartIndex)
                );
            } else {
                count += Popcount.popcount256A(
                    bitmap._data[bucket] & (MASK_FULL >> bucketStartIndex)
                );
                amount -= (256 - bucketStartIndex);
                bucket++;

                while(amount > 256) {
                    count += Popcount.popcount256A(bitmap._data[bucket]);
                    amount -= 256;
                    bucket++;
                }
                count += Popcount.popcount256A(
                    bitmap._data[bucket] & (MASK_FULL << (256 - amount))
                );
            }
        }
    }

    /**
     * @dev Returns number of set bits within a range.
     */
    function popcountB(BitMap storage bitmap, uint256 startIndex, uint256 amount) internal view returns(uint256 count) {
        uint256 bucket = startIndex >> 8;

        uint256 bucketStartIndex = (startIndex & 0xff);

        unchecked {
            if(bucketStartIndex + amount < 256) {
                count +=  Popcount.popcount256B(
                    bitmap._data[bucket] & (MASK_FULL << (256 - amount) >> bucketStartIndex)
                );
            } else {
                count += Popcount.popcount256B(
                    bitmap._data[bucket] & (MASK_FULL >> bucketStartIndex)
                );
                amount -= (256 - bucketStartIndex);
                bucket++;

                while(amount > 256) {
                    count += Popcount.popcount256B(bitmap._data[bucket]);
                    amount -= 256;
                    bucket++;
                }
                count += Popcount.popcount256B(
                    bitmap._data[bucket] & (MASK_FULL << (256 - amount))
                );
            }
        }
    }


    /**
     * @dev Find the closest index of the set bit before `index`.
     */
    function scanForward(BitMap storage bitmap, uint256 index) internal view returns (uint256 setBitIndex) {
        uint256 bucket = index >> 8;

        // index within the bucket
        uint256 bucketIndex = (index & 0xff);

        // load a bitboard from the bitmap.
        uint256 bb = bitmap._data[bucket];

        // offset the bitboard to scan from `bucketIndex`.
        bb = bb >> (0xff ^ bucketIndex); // bb >> (255 - bucketIndex)
        
        if(bb > 0) {
            unchecked {
                setBitIndex = (bucket << 8) | (bucketIndex -  bb.bitScanForward256());    
            }
        } else {
            while(true) {
                require(bucket > 0, "BitMaps: The set bit before the index doesn't exist.");
                unchecked {
                    bucket--;
                }
                // No offset. Always scan from the least significiant bit now.
                bb = bitmap._data[bucket];
                
                if(bb > 0) {
                    unchecked {
                        setBitIndex = (bucket << 8) | (255 -  bb.bitScanForward256());
                        break;
                    }
                } 
            }
        }
    }

    function getBucket(BitMap storage bitmap, uint256 bucket) internal view returns (uint256) {
        return bitmap._data[bucket];
    }
}

// File: @openzeppelin/contracts/security/ReentrancyGuard.sol


// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    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.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

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

// File: @openzeppelin/contracts/utils/introspection/IERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

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

// File: @openzeppelin/contracts/token/ERC721/IERC721.sol


// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;


/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

// File: @openzeppelin/contracts/utils/introspection/ERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;


/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// File: @openzeppelin/contracts/interfaces/IERC2981.sol


// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)

pragma solidity ^0.8.0;


/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 *
 * _Available since v4.5._
 */
interface IERC2981 is IERC165 {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}

// File: @openzeppelin/contracts/token/common/ERC2981.sol


// OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol)

pragma solidity ^0.8.0;



/**
 * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
 *
 * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
 * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
 *
 * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
 * fee is specified in basis points by default.
 *
 * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
 * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
 * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
 *
 * _Available since v4.5._
 */
abstract contract ERC2981 is IERC2981, ERC165 {
    struct RoyaltyInfo {
        address receiver;
        uint96 royaltyFraction;
    }

    RoyaltyInfo private _defaultRoyaltyInfo;
    mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
        return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @inheritdoc IERC2981
     */
    function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) {
        RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];

        if (royalty.receiver == address(0)) {
            royalty = _defaultRoyaltyInfo;
        }

        uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator();

        return (royalty.receiver, royaltyAmount);
    }

    /**
     * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
     * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
     * override.
     */
    function _feeDenominator() internal pure virtual returns (uint96) {
        return 10000;
    }

    /**
     * @dev Sets the royalty information that all ids in this contract will default to.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
        require(receiver != address(0), "ERC2981: invalid receiver");

        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Removes default royalty information.
     */
    function _deleteDefaultRoyalty() internal virtual {
        delete _defaultRoyaltyInfo;
    }

    /**
     * @dev Sets the royalty information for a specific token id, overriding the global default.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setTokenRoyalty(
        uint256 tokenId,
        address receiver,
        uint96 feeNumerator
    ) internal virtual {
        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
        require(receiver != address(0), "ERC2981: Invalid parameters");

        _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Resets royalty information for the token id back to the global default.
     */
    function _resetTokenRoyalty(uint256 tokenId) internal virtual {
        delete _tokenRoyaltyInfo[tokenId];
    }
}

// File: @openzeppelin/contracts/utils/Context.sol


// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

// File: erc721psi/contracts/ERC721Psi.sol


/**
  ______ _____   _____ ______ ___  __ _  _  _ 
 |  ____|  __ \ / ____|____  |__ \/_ | || || |
 | |__  | |__) | |        / /   ) || | \| |/ |
 |  __| |  _  /| |       / /   / / | |\_   _/ 
 | |____| | \ \| |____  / /   / /_ | |  | |   
 |______|_|  \_\\_____|/_/   |____||_|  |_|   

 - github: https://github.com/estarriolvetch/ERC721Psi
 - npm: https://www.npmjs.com/package/erc721psi
                                          
 */

pragma solidity ^0.8.0;

contract ERC721Psi is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;
    using BitMaps for BitMaps.BitMap;

    BitMaps.BitMap internal _batchHead;

    string private _name;
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) internal _owners;
    uint256 internal _currentIndex;

    mapping(uint256 => address) private _tokenApprovals;
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
        _currentIndex = _startTokenId();
    }

    /**
     * @dev Returns the starting token ID.
     * To change the starting token ID, please override this function.
     */
    function _startTokenId() internal pure virtual returns (uint256) {
        // It will become modifiable in the future versions
        return 0;
    }

    /**
     * @dev Returns the next token ID to be minted.
     */
    function _nextTokenId() internal view virtual returns (uint256) {
        return _currentIndex;
    }

    /**
     * @dev Returns the total amount of tokens minted in the contract.
     */
    function _totalMinted() internal view virtual returns (uint256) {
        return _currentIndex - _startTokenId();
    }


    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC165, IERC165)
        returns (bool)
    {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) 
        public 
        view 
        virtual 
        override 
        returns (uint) 
    {
        require(owner != address(0), "ERC721Psi: balance query for the zero address");

        uint count;
        for( uint i = _startTokenId(); i < _nextTokenId(); ++i ){
            if(_exists(i)){
                if( owner == ownerOf(i)){
                    ++count;
                }
            }
        }
        return count;
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId)
        public
        view
        virtual
        override
        returns (address)
    {
        (address owner, ) = _ownerAndBatchHeadOf(tokenId);
        return owner;
    }

    function _ownerAndBatchHeadOf(uint256 tokenId) internal view virtual returns (address owner, uint256 tokenIdBatchHead){
        require(_exists(tokenId), "ERC721Psi: owner query for nonexistent token");
        tokenIdBatchHead = _getBatchHead(tokenId);
        owner = _owners[tokenIdBatchHead];
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Psi: URI query for nonexistent token");

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overriden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }


    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ownerOf(tokenId);
        require(to != owner, "ERC721Psi: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721Psi: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId)
        public
        view
        virtual
        override
        returns (address)
    {
        require(
            _exists(tokenId),
            "ERC721Psi: approved query for nonexistent token"
        );

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved)
        public
        virtual
        override
    {
        require(operator != _msgSender(), "ERC721Psi: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator)
        public
        view
        virtual
        override
        returns (bool)
    {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "ERC721Psi: transfer caller is not owner nor approved"
        );

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public virtual override {
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "ERC721Psi: transfer caller is not owner nor approved"
        );
        _safeTransfer(from, to, tokenId, _data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `_data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(
            _checkOnERC721Received(from, to, tokenId, 1,_data),
            "ERC721Psi: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return tokenId < _nextTokenId() && _startTokenId() <= tokenId;
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId)
        internal
        view
        virtual
        returns (bool)
    {
        require(
            _exists(tokenId),
            "ERC721Psi: operator query for nonexistent token"
        );
        address owner = ownerOf(tokenId);
        return (spender == owner ||
            getApproved(tokenId) == spender ||
            isApprovedForAll(owner, spender));
    }

    /**
     * @dev Safely mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 quantity) internal virtual {
        _safeMint(to, quantity, "");
    }

    
    function _safeMint(
        address to,
        uint256 quantity,
        bytes memory _data
    ) internal virtual {
        uint256 nextTokenId = _nextTokenId();
        _mint(to, quantity);
        require(
            _checkOnERC721Received(address(0), to, nextTokenId, quantity, _data),
            "ERC721Psi: transfer to non ERC721Receiver implementer"
        );
    }


    function _mint(
        address to,
        uint256 quantity
    ) internal virtual {
        uint256 nextTokenId = _nextTokenId();
        
        require(quantity > 0, "ERC721Psi: quantity must be greater 0");
        require(to != address(0), "ERC721Psi: mint to the zero address");
        
        _beforeTokenTransfers(address(0), to, nextTokenId, quantity);
        _currentIndex += quantity;
        _owners[nextTokenId] = to;
        _batchHead.set(nextTokenId);
        _afterTokenTransfers(address(0), to, nextTokenId, quantity);
        
        // Emit events
        for(uint256 tokenId=nextTokenId; tokenId < nextTokenId + quantity; tokenId++){
            emit Transfer(address(0), to, tokenId);
        } 
    }



    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        (address owner, uint256 tokenIdBatchHead) = _ownerAndBatchHeadOf(tokenId);

        require(
            owner == from,
            "ERC721Psi: transfer of token that is not own"
        );
        require(to != address(0), "ERC721Psi: transfer to the zero address");

        _beforeTokenTransfers(from, to, tokenId, 1);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);   

        uint256 subsequentTokenId = tokenId + 1;

        if(!_batchHead.get(subsequentTokenId) &&  
            subsequentTokenId < _nextTokenId()
        ) {
            _owners[subsequentTokenId] = from;
            _batchHead.set(subsequentTokenId);
        }

        _owners[tokenId] = to;
        if(tokenId != tokenIdBatchHead) {
            _batchHead.set(tokenId);
        }

        emit Transfer(from, to, tokenId);

        _afterTokenTransfers(from, to, tokenId, 1);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits a {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param startTokenId uint256 the first ID of the tokens to be transferred
     * @param quantity uint256 amount of the tokens to be transfered.
     * @param _data bytes optional data to send along with the call
     * @return r bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity,
        bytes memory _data
    ) private returns (bool r) {
        if (to.isContract()) {
            r = true;
            for(uint256 tokenId = startTokenId; tokenId < startTokenId + quantity; tokenId++){
                try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                    r = r && retval == IERC721Receiver.onERC721Received.selector;
                } catch (bytes memory reason) {
                    if (reason.length == 0) {
                        revert("ERC721Psi: transfer to non ERC721Receiver implementer");
                    } else {
                        assembly {
                            revert(add(32, reason), mload(reason))
                        }
                    }
                }
            }
            return r;
        } else {
            return true;
        }
    }

    function _getBatchHead(uint256 tokenId) internal view returns (uint256 tokenIdBatchHead) {
        tokenIdBatchHead = _batchHead.scanForward(tokenId); 
    }


    function totalSupply() public virtual view returns (uint256) {
        return _totalMinted();
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`.
     *
     * This function scans the ownership mapping and is O(`totalSupply`) in complexity.
     * It is meant to be called off-chain.
     *
     * This function is compatiable with ERC721AQueryable.
     */
    function tokensOfOwner(address owner) external view virtual returns (uint256[] memory) {
        unchecked {
            uint256 tokenIdsIdx;
            uint256 tokenIdsLength = balanceOf(owner);
            uint256[] memory tokenIds = new uint256[](tokenIdsLength);
            for (uint256 i = _startTokenId(); tokenIdsIdx != tokenIdsLength; ++i) {
                if (_exists(i)) {
                    if (ownerOf(i) == owner) {
                        tokenIds[tokenIdsIdx++] = i;
                    }
                }
            }
            return tokenIds;   
        }
    }

    /**
     * @dev Hook that is called before a set of serially-ordered token ids are about to be transferred. This includes minting.
     *
     * startTokenId - the first token id to be transferred
     * quantity - the amount to be transferred
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     */
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Hook that is called after a set of serially-ordered token ids have been transferred. This includes
     * minting.
     *
     * startTokenId - the first token id to be transferred
     * quantity - the amount to be transferred
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero.
     * - `from` and `to` are never both zero.
     */
    function _afterTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}
}
// File: erc721psi/contracts/extension/ERC721PsiBurnable.sol


/**
  ______ _____   _____ ______ ___  __ _  _  _ 
 |  ____|  __ \ / ____|____  |__ \/_ | || || |
 | |__  | |__) | |        / /   ) || | \| |/ |
 |  __| |  _  /| |       / /   / / | |\_   _/ 
 | |____| | \ \| |____  / /   / /_ | |  | |   
 |______|_|  \_\\_____|/_/   |____||_|  |_|   
                                              
                                            
 */
pragma solidity ^0.8.0;




abstract contract ERC721PsiBurnable is ERC721Psi {
    using BitMaps for BitMaps.BitMap;
    BitMaps.BitMap internal _burnedToken;

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address from = ownerOf(tokenId);
        _beforeTokenTransfers(from, address(0), tokenId, 1);
        _burnedToken.set(tokenId);
        
        emit Transfer(from, address(0), tokenId);

        _afterTokenTransfers(from, address(0), tokenId, 1);
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view override virtual returns (bool){
        if(_burnedToken.get(tokenId)) {
            return false;
        } 
        return super._exists(tokenId);
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalMinted() - _burned();
    }

    /**
     * @dev Returns number of token burned.
     */
    function _burned() internal view returns (uint256 burned){
        uint256 startBucket = _startTokenId() >> 8;
        uint256 lastBucket = (_nextTokenId() >> 8) + 1;

        for(uint256 i=startBucket; i < lastBucket; i++) {
            uint256 bucket = _burnedToken.getBucket(i);
            burned += _popcount(bucket);
        }
    }

    /**
     * @dev Returns number of set bits.
     */
    function _popcount(uint256 x) private pure returns (uint256 count) {
        unchecked{
            for (count=0; x!=0; count++)
                x &= x - 1;
        }
    }
}
// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;


/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// File: EXO/NEW/EXO.sol

pragma solidity >=0.6.0;

/// @title Base64
/// @author Brecht Devos - <[email protected]>
/// @notice Provides functions for encoding/decoding base64
library Base64 {
    string internal constant TABLE_ENCODE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    bytes  internal constant TABLE_DECODE = hex"0000000000000000000000000000000000000000000000000000000000000000"
                                            hex"00000000000000000000003e0000003f3435363738393a3b3c3d000000000000"
                                            hex"00000102030405060708090a0b0c0d0e0f101112131415161718190000000000"
                                            hex"001a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132330000000000";

    function encode(bytes memory data) internal pure returns (string memory) {
        if (data.length == 0) return '';

        // load the table into memory
        string memory table = TABLE_ENCODE;

        // multiply by 4/3 rounded up
        uint256 encodedLen = 4 * ((data.length + 2) / 3);

        // add some extra buffer at the end required for the writing
        string memory result = new string(encodedLen + 32);

        assembly {
            // set the actual output length
            mstore(result, encodedLen)

            // prepare the lookup table
            let tablePtr := add(table, 1)

            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))

            // result ptr, jump over length
            let resultPtr := add(result, 32)

            // run over the input, 3 bytes at a time
            for {} lt(dataPtr, endPtr) {}
            {
                // read 3 bytes
                dataPtr := add(dataPtr, 3)
                let input := mload(dataPtr)

                // write 4 characters
                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(shr( 6, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(        input,  0x3F))))
                resultPtr := add(resultPtr, 1)
            }

            // padding with '='
            switch mod(mload(data), 3)
            case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }
            case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }
        }

        return result;
    }

    function decode(string memory _data) internal pure returns (bytes memory) {
        bytes memory data = bytes(_data);

        if (data.length == 0) return new bytes(0);
        require(data.length % 4 == 0, "invalid base64 decoder input");

        // load the table into memory
        bytes memory table = TABLE_DECODE;

        // every 4 characters represent 3 bytes
        uint256 decodedLen = (data.length / 4) * 3;

        // add some extra buffer at the end required for the writing
        bytes memory result = new bytes(decodedLen + 32);

        assembly {
            // padding with '='
            let lastBytes := mload(add(data, mload(data)))
            if eq(and(lastBytes, 0xFF), 0x3d) {
                decodedLen := sub(decodedLen, 1)
                if eq(and(lastBytes, 0xFFFF), 0x3d3d) {
                    decodedLen := sub(decodedLen, 1)
                }
            }

            // set the actual output length
            mstore(result, decodedLen)

            // prepare the lookup table
            let tablePtr := add(table, 1)

            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))

            // result ptr, jump over length
            let resultPtr := add(result, 32)

            // run over the input, 4 characters at a time
            for {} lt(dataPtr, endPtr) {}
            {
               // read 4 characters
               dataPtr := add(dataPtr, 4)
               let input := mload(dataPtr)

               // write 3 bytes
               let output := add(
                   add(
                       shl(18, and(mload(add(tablePtr, and(shr(24, input), 0xFF))), 0xFF)),
                       shl(12, and(mload(add(tablePtr, and(shr(16, input), 0xFF))), 0xFF))),
                   add(
                       shl( 6, and(mload(add(tablePtr, and(shr( 8, input), 0xFF))), 0xFF)),
                               and(mload(add(tablePtr, and(        input , 0xFF))), 0xFF)
                    )
                )
                mstore(resultPtr, shl(232, output))
                resultPtr := add(resultPtr, 3)
            }
        }

        return result;
    }
}






pragma solidity ^0.8.7;


abstract contract MerkleProof {
    mapping(uint256 => bytes32) internal _wlMerkleRoot;
    mapping(uint256 => bytes32) internal _alMerkleRoot;

    uint256 public phaseId;
    function _setWlMerkleRoot(bytes32 merkleRoot_) internal virtual {
        _wlMerkleRoot[phaseId] = merkleRoot_;
    }

    function _setWlMerkleRootWithId(uint256 _phaseId,bytes32 merkleRoot_) internal virtual {
        _wlMerkleRoot[_phaseId] = merkleRoot_;
    }
    function isWhitelisted(address address_, uint256 _phaseId, uint256 wlCount, bytes32[] memory proof_) public view returns (bool) {
        bytes32 _leaf = keccak256(abi.encodePacked(address_, wlCount));
        for (uint256 i = 0; i < proof_.length; i++) {
            _leaf = _leaf < proof_[i] ? keccak256(abi.encodePacked(_leaf, proof_[i])) : keccak256(abi.encodePacked(proof_[i], _leaf));
        }
        return _leaf == _wlMerkleRoot[_phaseId];
    }

    function _setAlMerkleRootWithId(uint256 _phaseId,bytes32 merkleRoot_) internal virtual {
        _alMerkleRoot[_phaseId] = merkleRoot_;
    }

    function _setAlMerkleRoot(bytes32 merkleRoot_) internal virtual {
        _alMerkleRoot[phaseId] = merkleRoot_;
    }

    function isAllowlisted(address address_,uint256 _alId, bytes32[] memory proof_) public view returns (bool) {
        bytes32 _leaf = keccak256(abi.encodePacked(address_));
        for (uint256 i = 0; i < proof_.length; i++) {
            _leaf = _leaf < proof_[i] ? keccak256(abi.encodePacked(_leaf, proof_[i])) : keccak256(abi.encodePacked(proof_[i], _leaf));
        }
        return _leaf == _alMerkleRoot[_alId];
    }

}

pragma solidity ^0.8.9;
abstract contract Operable is Context {
    mapping(address => bool) _operators;
    modifier onlyOperator() {
        _checkOperatorRole(_msgSender());
        _;
    }
    function isOperator(address _operator) public view returns (bool) {
        return _operators[_operator];
    }
    function _grantOperatorRole(address _candidate) internal {
        require(
            !_operators[_candidate],
            string(
                abi.encodePacked(
                    "account ",
                    Strings.toHexString(uint160(_msgSender()), 20),
                    " is already has an operator role"
                )
            )
        );
        _operators[_candidate] = true;
    }
    function _revokeOperatorRole(address _candidate) internal {
        _checkOperatorRole(_candidate);
        delete _operators[_candidate];
    }
    function _checkOperatorRole(address _operator) internal view {
        require(
            _operators[_operator],
            string(
                abi.encodePacked(
                    "account ",
                    Strings.toHexString(uint160(_msgSender()), 20),
                    " is not an operator"
                )
            )
        );
    }
}

pragma solidity ^0.8.13;

interface IOperatorFilterRegistry {
    function isOperatorAllowed(address registrant, address operator) external view returns (bool);
    function register(address registrant) external;
    function registerAndSubscribe(address registrant, address subscription) external;
    function registerAndCopyEntries(address registrant, address registrantToCopy) external;
    function unregister(address addr) external;
    function updateOperator(address registrant, address operator, bool filtered) external;
    function updateOperators(address registrant, address[] calldata operators, bool filtered) external;
    function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external;
    function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external;
    function subscribe(address registrant, address registrantToSubscribe) external;
    function unsubscribe(address registrant, bool copyExistingEntries) external;
    function subscriptionOf(address addr) external returns (address registrant);
    function subscribers(address registrant) external returns (address[] memory);
    function subscriberAt(address registrant, uint256 index) external returns (address);
    function copyEntriesOf(address registrant, address registrantToCopy) external;
    function isOperatorFiltered(address registrant, address operator) external returns (bool);
    function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool);
    function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool);
    function filteredOperators(address addr) external returns (address[] memory);
    function filteredCodeHashes(address addr) external returns (bytes32[] memory);
    function filteredOperatorAt(address registrant, uint256 index) external returns (address);
    function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32);
    function isRegistered(address addr) external returns (bool);
    function codeHashOf(address addr) external returns (bytes32);
}

pragma solidity ^0.8.13;


/**
 * @title  OperatorFilterer
 * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another
 *         registrant's entries in the OperatorFilterRegistry.
 * @dev    This smart contract is meant to be inherited by token contracts so they can use the following:
 *         - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods.
 *         - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods.
 */
abstract contract OperatorFilterer {
    error OperatorNotAllowed(address operator);
    bool public operatorFilteringEnabled = true;

    IOperatorFilterRegistry public constant OPERATOR_FILTER_REGISTRY =
        IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);

    constructor(address subscriptionOrRegistrantToCopy, bool subscribe) {
        // If an inheriting token contract is deployed to a network without the registry deployed, the modifier
        // will not revert, but the contract will need to be registered with the registry once it is deployed in
        // order for the modifier to filter addresses.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            if (subscribe) {
                OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy);
            } else {
                if (subscriptionOrRegistrantToCopy != address(0)) {
                    OPERATOR_FILTER_REGISTRY.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy);
                } else {
                    OPERATOR_FILTER_REGISTRY.register(address(this));
                }
            }
        }
    }

    modifier onlyAllowedOperator(address from) virtual {
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0 && operatorFilteringEnabled) {
            // Allow spending tokens from addresses with balance
            // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred
            // from an EOA.
            if (from == msg.sender) {
                _;
                return;
            }
            if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), msg.sender)) {
                revert OperatorNotAllowed(msg.sender);
            }
        }
        _;
    }

    modifier onlyAllowedOperatorApproval(address operator) virtual {
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0 && operatorFilteringEnabled) {
            if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) {
                revert OperatorNotAllowed(operator);
            }
        }
        _;
    }
}


pragma solidity ^0.8.13;
/**
 * @title  DefaultOperatorFilterer
 * @notice Inherits from OperatorFilterer and automatically subscribes to the default OpenSea subscription.
 */
abstract contract DefaultOperatorFilterer is OperatorFilterer {
    address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6);

    constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {}
}





pragma solidity >=0.7.0 <0.9.0;

interface IContractAllowListProxy {
    function isAllowed(address _transferer, uint256 _level)
        external
        view
        returns (bool);
}

pragma solidity >=0.8.0;

/// @title IERC721RestrictApprove
/// @dev Approve抑制機能付きコントラクトのインターフェース
/// @author Lavulite

interface IERC721RestrictApprove {
    /**
     * @dev CALレベルが変更された場合のイベント
     */
    event CalLevelChanged(address indexed operator, uint256 indexed level);
    
    /**
     * @dev LocalContractAllowListnに追加された場合のイベント
     */
    event LocalCalAdded(address indexed operator, address indexed transferer);

    /**
     * @dev LocalContractAllowListnに削除された場合のイベント
     */
    event LocalCalRemoved(address indexed operator, address indexed transferer);

    /**
     * @dev CALを利用する場合のCALのレベルを設定する。レベルが高いほど、許可されるコントラクトの範囲が狭い。
     */
    function setCALLevel(uint256 level) external;

    /**
     * @dev CALのアドレスをセットする。
     */
    function setCAL(address calAddress) external;

    /**
     * @dev CALのリストに無い独自の許可アドレスを追加する場合、こちらにアドレスを記載する。
     */
    function addLocalContractAllowList(address transferer) external;

    /**
     * @dev CALのリストにある独自の許可アドレスを削除する場合、こちらにアドレスを記載する。
     */
    function removeLocalContractAllowList(address transferer) external;

    /**
     * @dev CALのリストにある独自の許可アドレスの一覧を取得する。
     */
    function getLocalContractAllowList() external view returns(address[] memory);

}

pragma solidity >=0.8.0;

/// @title AntiScam機能付きERC721A
/// @dev Readmeを見てください。

abstract contract ERC721RestrictApprove is ERC721PsiBurnable, IERC721RestrictApprove {
    using EnumerableSet for EnumerableSet.AddressSet;

    IContractAllowListProxy public CAL;
    EnumerableSet.AddressSet localAllowedAddresses;

    modifier onlyHolder(uint256 tokenId) {
        require(
            msg.sender == ownerOf(tokenId),
            "RestrictApprove: operation is only holder."
        );
        _;
    }

    /*//////////////////////////////////////////////////////////////
    変数
    //////////////////////////////////////////////////////////////*/
    bool public enableRestrict = true;

    // token lock
    mapping(uint256 => uint256) public tokenCALLevel;

    // wallet lock
    mapping(address => uint256) public walletCALLevel;

    // contract lock
    uint256 public CALLevel = 1;

    /*///////////////////////////////////////////////////////////////
    Approve抑制機能ロジック
    //////////////////////////////////////////////////////////////*/
    function _addLocalContractAllowList(address transferer)
        internal
        virtual
    {
        localAllowedAddresses.add(transferer);
        emit LocalCalAdded(msg.sender, transferer);
    }

    function _removeLocalContractAllowList(address transferer)
        internal
        virtual
    {
        localAllowedAddresses.remove(transferer);
        emit LocalCalRemoved(msg.sender, transferer);
    }

    function _getLocalContractAllowList()
        internal
        virtual
        view
        returns(address[] memory)
    {
        return localAllowedAddresses.values();
    }

    function _isLocalAllowed(address transferer)
        internal
        view
        virtual
        returns (bool)
    {
        return localAllowedAddresses.contains(transferer);
    }

    function _isAllowed(address transferer)
        internal
        view
        virtual
        returns (bool)
    {
        return _isAllowed(msg.sender, transferer);
    }

    function _isAllowed(uint256 tokenId, address transferer)
        internal
        view
        virtual
        returns (bool)
    {
        uint256 level = _getCALLevel(msg.sender, tokenId);
        return _isAllowed(transferer, level);
    }

    function _isAllowed(address holder, address transferer)
        internal
        view
        virtual
        returns (bool)
    {
        uint256 level = _getCALLevel(holder);
        return _isAllowed(transferer, level);
    }

    function _isAllowed(address transferer, uint256 level)
        internal
        view
        virtual
        returns (bool)
    {
        if (!enableRestrict) {
            return true;
        }

        return _isLocalAllowed(transferer) || CAL.isAllowed(transferer, level);
    }

    function _getCALLevel(address holder, uint256 tokenId)
        internal
        view
        virtual
        returns (uint256)
    {
        if (tokenCALLevel[tokenId] > 0) {
            return tokenCALLevel[tokenId];
        }

        return _getCALLevel(holder);
    }

    function _getCALLevel(address holder)
        internal
        view
        virtual
        returns (uint256)
    {
        if (walletCALLevel[holder] > 0) {
            return walletCALLevel[holder];
        }

        return CALLevel;
    }

    function _setCAL(address _cal) internal virtual {
        CAL = IContractAllowListProxy(_cal);
    }

    function _deleteTokenCALLevel(uint256 tokenId) internal virtual {
        delete tokenCALLevel[tokenId];
    }

    function setTokenCALLevel(uint256 tokenId, uint256 level)
        external
        virtual
        onlyHolder(tokenId)
    {
        tokenCALLevel[tokenId] = level;
    }

    function setWalletCALLevel(uint256 level)
        external
        virtual
    {
        walletCALLevel[msg.sender] = level;
    }

    /*///////////////////////////////////////////////////////////////
                              OVERRIDES
    //////////////////////////////////////////////////////////////*/

    function isApprovedForAll(address owner, address operator)
        public
        view
        virtual
        override
        returns (bool)
    {
        if (_isAllowed(owner, operator) == false) {
            return false;
        }
        return super.isApprovedForAll(owner, operator);
    }

    function setApprovalForAll(address operator, bool approved)
        public
        virtual
        override
    {
        require(
            _isAllowed(operator) || approved == false,
            "RestrictApprove: Can not approve locked token"
        );
        super.setApprovalForAll(operator, approved);
    }

    function _beforeApprove(address to, uint256 tokenId)
        internal
        virtual
    {
        if (to != address(0)) {
            require(_isAllowed(tokenId, to), "RestrictApprove: The contract is not allowed.");
        }
    }

    function approve(address to, uint256 tokenId)
        public
        virtual
        override
    {
        _beforeApprove(to, tokenId);
        super.approve(to, tokenId);
    }

    function _afterTokenTransfers(
        address from,
        address, /*to*/
        uint256 startTokenId,
        uint256 /*quantity*/
    ) internal virtual override {
        // 転送やバーンにおいては、常にstartTokenIdは TokenIDそのものとなります。
        if (from != address(0)) {
            // CALレベルをデフォルトに戻す。
            _deleteTokenCALLevel(startTokenId);
        }
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override
        returns (bool)
    {
        return
            interfaceId == type(IERC721RestrictApprove).interfaceId ||
            super.supportsInterface(interfaceId);
    }
}


pragma solidity ^0.8.7;
/*
╭━━━┳━━━┳━━╮╱╭━━╮╭━━━┳━━━┳━━┳━╮╱╭┳━━━╮
┃╭━╮┃╭━━┫╭╮┃╱┃╭╮┃┃╭━━┫╭━╮┣┫┣┫┃╰╮┃┃╭━╮┃
┃┃╱┃┃╰━━┫╰╯╰╮┃╰╯╰┫╰━━┫┃╱╰╯┃┃┃╭╮╰╯┃╰━━╮
┃╰━╯┃╭━━┫╭━╮┃┃╭━╮┃╭━━┫┃╭━╮┃┃┃┃╰╮┃┣━━╮┃
┃╭━╮┃╰━━┫╰━╯┃┃╰━╯┃╰━━┫╰┻━┣┫┣┫┃╱┃┃┃╰━╯┃
╰╯╱╰┻━━━┻━━━╯╰━━━┻━━━┻━━━┻━━┻╯╱╰━┻━━━╯
*/
contract AEBBEGINS is Ownable, ERC721RestrictApprove, ReentrancyGuard, MerkleProof, ERC2981, DefaultOperatorFilterer,Operable {
  //Project Settings
  mapping(uint256 => uint256) public alMintPrice;
  uint256 public psMintPrice = 0.05 ether;
  uint256 public wlMintPrice;  
  mapping(uint256 => uint256) public maxMintsPerAL;
  uint256 public maxMintsPerPS = 2;
  uint256 public maxMintsPerALOT = 30;
  uint256 public maxMintsPerPSOT = 2;
  uint256 public maxSupply;
  uint256 public mintable;
  uint256 public revealed;
  uint256 public nowPhaseWl;
  uint256 public nowPhaseAl;
  uint256 public nowPhasePs;

  address internal _withdrawWallet;
  address internal _aa;
  address internal _bb;
  address internal _cc;
  address internal _dd;
  address internal _ee;
  address internal _ff;

  uint256 internal _aaPerc;
  uint256 internal _bbPerc;
  uint256 internal _ccPerc;
  uint256 internal _ddPerc;
  uint256 internal _eePerc;
  uint256 internal _ffPerc;

  //URI
  string internal hiddenURI;
  string internal _baseTokenURI;
  string public _baseExtension = ".json";

  //flags
  mapping(uint256 => bool) public isWlSaleEnabled;
  mapping(uint256 => bool) public isAlSaleEnabled;
  bool public isPublicSaleEnabled;
  bool internal lockBurn = true;

  //mint records.
  mapping(uint256 => uint256) public phaseIds;
  mapping(uint256 => mapping(address => uint256)) internal _wlMinted;
  mapping(uint256 => mapping(uint256 => mapping(address => uint256))) internal _alMinted;
  mapping(uint256 => mapping(address => uint256)) internal _psMinted;
  
  constructor (
    address _royaltyReceiver,
    uint96 _royaltyFraction,
    uint256 _aaPercAdd
  ) ERC721Psi ("AEB BEGINS","AEB") {
    _grantOperatorRole(msg.sender);
    _grantOperatorRole(_royaltyReceiver);
    _setDefaultRoyalty(_royaltyReceiver,_royaltyFraction);
    //CAL initialization
    setCALLevel(1);
    _setCAL(0xF2A78c73ffBAB6ECc3548Acc54B546ace279312E);//Ethereum mainnet proxy
    _addLocalContractAllowList(0x1E0049783F008A0085193E00003D00cd54003c71);//OpenSea
    _addLocalContractAllowList(0x4feE7B061C97C9c496b01DbcE9CDb10c02f0a0Be);//Rarible
    maxMintsPerAL[0] = 10;//fcfs
    maxMintsPerAL[1] = 30;//VVIP1
    maxMintsPerAL[2] = 20;//VVIP2
    maxMintsPerAL[3] = 20;//VIP1
    maxMintsPerAL[4] = 20;//VIP2
    maxMintsPerAL[5] = 10;//VIP3
    maxMintsPerAL[6] = 10;//VIP4
    maxMintsPerAL[7] = 10;//kaku

    alMintPrice[0] = 0.05 ether;//fcfs
    alMintPrice[1] = 0.02 ether;//VVIP1
    alMintPrice[2] = 0.03 ether;//VVIP2
    alMintPrice[3] = 0.025 ether;//VIP1
    alMintPrice[4] = 0.035 ether;//VIP2
    alMintPrice[5] = 0.04 ether;//VIP3
    alMintPrice[6] = 0.045 ether;//VIP4
    alMintPrice[7] = 0.05 ether;//k
    
    hiddenURI = "https://arweave.net/QQCSg9F1i63yAUu7NRLT5ncvDE3HCrqFxpl6K8iboh4";
    _aa = msg.sender;
    _aaPerc = _aaPercAdd;
  }
  //start from 1.adjust.
  function _startTokenId() internal pure virtual override returns (uint256) {
        return 1;
  }
  //set Default Royalty._feeNumerator 500 = 5% Royalty
  function setDefaultRoyalty(address _receiver, uint96 _feeNumerator) external virtual onlyOperator {
      _setDefaultRoyalty(_receiver, _feeNumerator);
  }
  //for ERC2981
  function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721RestrictApprove, ERC2981) returns (bool) {
    return super.supportsInterface(interfaceId);
  }
  //for ERC2981 Opensea
  function contractURI() external view virtual returns (string memory) {
        return _formatContractURI();
  }
  //make contractURI
  function _formatContractURI() internal view returns (string memory) {
    (address receiver, uint256 royaltyFraction) = royaltyInfo(0,_feeDenominator());//tokenid=0
    return string(
      abi.encodePacked(
        "data:application/json;base64,",
        Base64.encode(
          bytes(
            abi.encodePacked(
                '{"seller_fee_basis_points":', Strings.toString(royaltyFraction),
                ', "fee_recipient":"', Strings.toHexString(uint256(uint160(receiver)), 20), '"}'
            )
          )
        )
      )
    );
  }
  //set maxSupply.only owner.
  function setMaxSupply(uint256 _maxSupply) external virtual onlyOperator {
    maxSupply = _maxSupply;
  }
  //set mintable.only owner.
  function setMintable(uint256 _mintable) external virtual onlyOperator {
    mintable = _mintable;
  }
    // GET phaseId.
  function getPhaseIds(uint256 _alId) external view virtual returns (uint256){
    return phaseIds[_alId];
  }
    // SET phaseId.
  function setPhaseId(uint256 _alId,uint256 _phaseId) external virtual onlyOperator {
    phaseIds[_alId] = _phaseId;
  }
    // SET phaseId.
  function setPhaseIdWithReset(uint256 _alId,uint256 _phaseId) external virtual onlyOperator {
    phaseIds[_alId] = _phaseId;
    nowPhaseAl += 1;
  }
  function setNowPhaseWl(uint256 _nowPhaseWl) external virtual onlyOperator {
    nowPhaseWl = _nowPhaseWl;
  }
  function setNowPhaseAl(uint256 _nowPhaseAl) external virtual onlyOperator {
    nowPhaseAl = _nowPhaseAl;
  }
  function setNowPhasePs(uint256 _nowPhasePs) external virtual onlyOperator {
    nowPhasePs = _nowPhasePs;
  }
  // SET PRICES.
  //WL.Price
  function setWlPrice(uint256 newPrice) external virtual onlyOperator {
    wlMintPrice = newPrice;
  }
  //AL.Price
  function setAlPrice(uint256 _alId,uint256 newPrice) external virtual onlyOperator {
    alMintPrice[_alId] = newPrice;
  }
  //PS.Price
  function setPsPrice(uint256 newPrice) external virtual onlyOperator {
    psMintPrice = newPrice;
  }
  //set reveal.only owner.
  function setReveal(uint256 newRevealNum) external virtual onlyOperator {
    revealed = newRevealNum;
  }
  //return _isRevealed()
  function _isRevealed(uint256 _tokenId) internal view virtual returns (bool){
    return _tokenId <= revealed;
  }
  // GET MINTED COUNT.
  function wlMinted(address _address) external view virtual returns (uint256){
    return _wlMinted[nowPhaseWl][_address];
  }
  function alMinted(address _address) external view virtual returns (uint256){
    return _alMinted[nowPhaseAl][phaseIds[nowPhaseAl]][_address];
  }
  function alIdMinted(uint256 _nowPhaseAl,address _address) external view virtual returns (uint256){
    return _alMinted[_nowPhaseAl][phaseIds[_nowPhaseAl]][_address];
  }
  function psMinted(address _address) external view virtual returns (uint256){
    return _psMinted[nowPhasePs][_address];
  }
  // SET MAX MINTS.
  //get.AL.mxmints
  function getAlMaxMints() external view virtual returns (uint256){
    return maxMintsPerAL[phaseId];
  }
  //set.AL.mxmints
  function setAlMaxMints(uint256 _alId,uint256 _max) external virtual onlyOperator {
    maxMintsPerAL[_alId] = _max;
  }
  //PS.mxmints
  function setPsMaxMints(uint256 _max) external virtual onlyOperator {
    maxMintsPerPS = _max;
  }
  // SET SALES ENABLE.
  //WL.SaleEnable
  function setWhitelistSaleEnable(uint256 _phaseId,bool bool_) external virtual onlyOperator {
    isWlSaleEnabled[_phaseId] = bool_;
  }

  //AL.SaleEnable
  function setAllowlistSaleEnable(uint256 _alId,bool bool_) external virtual onlyOperator {
    isAlSaleEnabled[_alId] = bool_;
  }
  //PS.SaleEnable
  function setPublicSaleEnable(bool bool_) external virtual onlyOperator {
    isPublicSaleEnabled = bool_;
  }

  function setMerkleRootWl(bytes32 merkleRoot_) external virtual onlyOperator {
    _setWlMerkleRoot(merkleRoot_);
  }

  function setMerkleRootWlWithId(uint256 _phaseId,bytes32 merkleRoot_) external virtual onlyOperator {
    _setWlMerkleRootWithId(_phaseId,merkleRoot_);
  }

  function setMerkleRootAlWithId(uint256 _phaseId,bytes32 merkleRoot_) external virtual onlyOperator {
    _setAlMerkleRootWithId(_phaseId,merkleRoot_);
  }
  //set HiddenBaseURI.only owner.
  function setHiddenURI(string memory uri_) external virtual onlyOperator {
    hiddenURI = uri_;
  }
  //return _currentIndex
  function getCurrentIndex() external view virtual returns (uint256){
    return _nextTokenId() -1;
  }
  /** @dev set BaseURI at after reveal. only owner. */
  function setBaseURI(string memory uri_) external virtual onlyOperator {
    _baseTokenURI = uri_;
  }

  function setBaseExtension(string memory _newBaseExtension) external onlyOperator
  {
    _baseExtension = _newBaseExtension;
  }

  /** @dev BaseURI.internal. */
  function _currentBaseURI() internal view returns (string memory){
    return _baseTokenURI;
  }

  function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) {
    require(_exists(_tokenId), "URI query for nonexistent token");
    if(_isRevealed(_tokenId)){
        return string(abi.encodePacked(_currentBaseURI(), Strings.toString(_tokenId), _baseExtension));
    }
    return hiddenURI;
  }
  
  /** @dev owner mint.transfer to _address.only owner. */
  function ownerMintSafe(uint256 _amount, address _address) external virtual onlyOperator { 
    require((_amount + totalSupply()) <= (maxSupply) || maxSupply == 0, "No more NFTs");
    _safeMint(_address, _amount);
  }
  
  //WL mint.
  function whitelistMint(uint256 _phaseId,uint256 _amount, uint256 wlcount, bytes32[] memory proof_) external payable virtual nonReentrant {
    require(isWlSaleEnabled[_phaseId], "whitelistMint is Paused");
    require(isWhitelisted(msg.sender,_phaseId, wlcount, proof_), "You are not whitelisted!");
    require(wlcount > 0, "You have no WL!");
    require(wlcount >= _amount, "whitelistMint: Over max mints per wallet");
    require(wlcount >= _wlMinted[_phaseId][msg.sender] + _amount, "You have no whitelistMint left");
    require(msg.value == wlMintPrice * _amount, "ETH value is not correct");
    require((_amount + totalSupply()) <= (mintable) || mintable == 0, "No more NFTs");
    _wlMinted[_phaseId][msg.sender] += _amount;
    _safeMint(msg.sender, _amount);
  }
  
  //AL mint.
  function allowlistMint(uint256 _alId,uint256 _amount, bytes32[] memory proof_) external payable virtual nonReentrant {
    require(isAlSaleEnabled[_alId], "allowlistMint is Paused");
    require(isAllowlisted(msg.sender,_alId, proof_), "You are not whitelisted!");
    require(maxMintsPerALOT >= _amount, "allowlistMint: Over max mints per one time");
    require(maxMintsPerAL[_alId] >= _amount, "allowlistMint: Over max mints per wallet");
    require(maxMintsPerAL[_alId] >= _alMinted[_alId][phaseIds[_alId]][msg.sender] + _amount, "You have no whitelistMint left");
    require(msg.value == alMintPrice[_alId] * _amount, "ETH value is not correct");
    require((_amount + totalSupply()) <= (mintable) || mintable == 0, "No more NFTs");
    _alMinted[_alId][phaseIds[_alId]][msg.sender] += _amount;
    _safeMint(msg.sender, _amount);
  }

  //Public mint.
  function publicMint(uint256 _amount) external payable virtual nonReentrant {
    require(isPublicSaleEnabled, "publicMint is Paused");
    require(maxMintsPerPSOT >= _amount, "publicMint: Over max mints per one time");
    require(maxMintsPerPS >= _amount, "publicMint: Over max mints per wallet");
    require(maxMintsPerPS >= _psMinted[nowPhasePs][msg.sender] + _amount, "You have no publicMint left");
    require(msg.value == psMintPrice * _amount, "ETH value is not correct");
    require((_amount + totalSupply()) <= (mintable) || mintable == 0, "No more NFTs");
    _psMinted[nowPhasePs][msg.sender] += _amount;
    _safeMint(msg.sender, _amount);
  }

  /** @dev receive. */
  function receiveToDeb() external payable virtual onlyOperator nonReentrant {
      require(msg.value > 0, "ETH value is not correct");
  }

  /** @dev widraw ETH from this contract.only operator. */
  function withdraw() external payable virtual onlyOperator nonReentrant{
    require((_aa != address(0) && _aaPerc != 0) || _aa == address(0),"please set withdraw Address_aa and percentage.");
    require((_bb != address(0) && _bbPerc != 0) || _bb == address(0),"please set withdraw Address_bb and percentage.");
    require((_cc != address(0) && _ccPerc != 0) || _cc == address(0),"please set withdraw Address_cc and percentage.");
    require((_dd != address(0) && _ddPerc != 0) || _dd == address(0),"please set withdraw Address_dd and percentage.");
    require((_ee != address(0) && _eePerc != 0) || _ee == address(0),"please set withdraw Address_ee and percentage.");
    require((_ff != address(0) && _ffPerc != 0) || _ff == address(0),"please set withdraw Address_ff and percentage.");
    uint256 _ethBalance = address(this).balance;
    bool os;
    if(_aa != address(0)){//if _aa has.
        (os, ) = payable(_aa).call{value: (_ethBalance * _aaPerc/10000)}("");
        require(os, "Failed to withdraw_aa Ether");
    }
    if(_bb != address(0)){//if _bb has.
        (os, ) = payable(_bb).call{value: (_ethBalance * _bbPerc/10000)}("");
        require(os, "Failed to withdraw_bb Ether");
    }
    if(_cc != address(0)){//if _cc has.
        (os, ) = payable(_cc).call{value: (_ethBalance * _ccPerc/10000)}("");
        require(os, "Failed to withdraw_cc Ether");
    }
    if(_dd != address(0)){//if _dd has.
        (os, ) = payable(_dd).call{value: (_ethBalance * _ddPerc/10000)}("");
        require(os, "Failed to withdraw_dd Ether");
    }
    if(_ee != address(0)){//if _ee has.
        (os, ) = payable(_ee).call{value: (_ethBalance * _eePerc/10000)}("");
        require(os, "Failed to withdraw_ee Ether");
    }
    if(_ff != address(0)){//if _ff has.
        (os, ) = payable(_ff).call{value: (_ethBalance * _ffPerc/10000)}("");
        require(os, "Failed to withdraw_ff Ether");
    }
    _ethBalance = address(this).balance;
    if(_withdrawWallet != address(0)){//if _withdrawWallet has.
        (os, ) = payable(_withdrawWallet).call{value: (_ethBalance)}("");
    }else{
        (os, ) = payable(owner()).call{value: (_ethBalance)}("");
    }
    require(os, "Failed to withdraw Ether");
  }

    //burn
    function burn(uint256 tokenId) external virtual {
        require(ownerOf(tokenId) == msg.sender, "isnt owner token");
        require(lockBurn == false, "not allow");
        _burn(tokenId);
    }
    // //set.LockBurn
    function setLockBurn(bool bool_) external virtual onlyOperator {
        lockBurn = bool_;
    }

  //return wallet owned tokenids.
  function walletOfOwner(address _address) external view virtual returns (uint256[] memory) {
    uint256 ownerTokenCount = balanceOf(_address);
    uint256[] memory tokenIds = new uint256[](ownerTokenCount);
    //search from all tonkenid. so spend high gas values.attention.
    uint256 tokenindex = 0;
    for (uint256 i = _startTokenId(); i < (_nextTokenId() -1); i++) {
      if(_address == this.tryOwnerOf(i)) tokenIds[tokenindex++] = i;
    }
    return tokenIds;
  }

    //try catch vaersion ownerOf. support burned tokenid.
    function tryOwnerOf(uint256 tokenId) external view  virtual returns (address) {
        try this.ownerOf(tokenId) returns (address _address) {
            return(_address);
        } catch {
            return (address(0));//return 0x0 if error.
        }
    }


  /**
    @dev set aa's wallet and fraction.withdraw to this wallet.only operator.
    */
  function setWallet__aa(address _owner,uint256 _perc) external virtual onlyOperator {
    _aa = _owner;
    _aaPerc = _perc;
  }

  /**
    @dev set bb's wallet and fraction.withdraw to this wallet.only operator.
    */
  function setWallet__bb(address _owner,uint256 _perc) external virtual onlyOperator {
    _bb = _owner;
    _bbPerc = _perc;
  }

  /**
    @dev set cc's wallet and fraction.withdraw to this wallet.only operator.
    */
  function setWallet__cc(address _owner,uint256 _perc) external virtual onlyOperator {
    _cc = _owner;
    _ccPerc = _perc;
  }

  /**
    @dev set dd's wallet and fraction.withdraw to this wallet.only operator.
    */
  function setWallet__dd(address _owner,uint256 _perc) external virtual onlyOperator {
    _dd = _owner;
    _ddPerc = _perc;
  }

  /**
    @dev set ee's wallet and fraction.withdraw to this wallet.only operator.
    */
  function setWallet__ee(address _owner,uint256 _perc) external virtual onlyOperator {
    _ee = _owner;
    _eePerc = _perc;
  }

  /**
    @dev set ff's wallet and fraction.withdraw to this wallet.only operator.
    */
  function setWallet__ff(address _owner,uint256 _perc) external virtual onlyOperator {
    _ff = _owner;
    _ffPerc = _perc;
  }
  /**
    @dev set withdraw's wallet.withdraw to this wallet.only operator.
    */
  function setWallet__ww(address _owner) external virtual onlyOperator {
    _withdrawWallet = _owner;
  }

    //OPENSEA.OPERATORFilterer.START
    /**
     * @notice Set the state of the OpenSea operator filter
     * @param value Flag indicating if the operator filter should be applied to transfers and approvals
     */
    function setOperatorFilteringEnabled(bool value) external onlyOperator {
        operatorFilteringEnabled = value;
    }

    function setApprovalForAll(address operator, bool approved) public override onlyAllowedOperatorApproval(operator) {
        super.setApprovalForAll(operator, approved);
    }

    function approve(address operator, uint256 tokenId) public override onlyAllowedOperatorApproval(operator) {
        super.approve(operator, tokenId);
    }

    function transferFrom(address from, address to, uint256 tokenId) public override onlyAllowedOperator(from) {
        super.transferFrom(from, to, tokenId);
    }

    function safeTransferFrom(address from, address to, uint256 tokenId) public override onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, tokenId);
    }

    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data)
        public
        override
        onlyAllowedOperator(from)
    {
        super.safeTransferFrom(from, to, tokenId, data);
    }
    //OPENSEA.OPERATORFilterer.END

    /*///////////////////////////////////////////////////////////////
                    OVERRIDES ERC721RestrictApprove
    //////////////////////////////////////////////////////////////*/
    function addLocalContractAllowList(address transferer)
        external
        override
        onlyOperator
    {
        _addLocalContractAllowList(transferer);
    }

    function removeLocalContractAllowList(address transferer)
        external
        override
        onlyOperator
    {
        _removeLocalContractAllowList(transferer);
    }

    function getLocalContractAllowList()
        external
        override
        view
        returns(address[] memory)
    {
        return _getLocalContractAllowList();
    }

    function setCALLevel(uint256 level) public override onlyOperator {
        CALLevel = level;
    }

    function setCAL(address calAddress) external override onlyOperator {
        _setCAL(calAddress);
    }

    /**
        @dev Operable.Role.ADD
     */
    function grantOperatorRole(address _candidate) external onlyOwner {
        _grantOperatorRole(_candidate);
    }
    /**
        @dev Operable.Role.REMOVE
     */
    function revokeOperatorRole(address _candidate) external onlyOwner {
        _revokeOperatorRole(_candidate);
    }
    
}
//CODE.BY.FRICKLIK

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_royaltyReceiver","type":"address"},{"internalType":"uint96","name":"_royaltyFraction","type":"uint96"},{"internalType":"uint256","name":"_aaPercAdd","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"uint256","name":"level","type":"uint256"}],"name":"CalLevelChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"transferer","type":"address"}],"name":"LocalCalAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"transferer","type":"address"}],"name":"LocalCalRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"CAL","outputs":[{"internalType":"contract IContractAllowListProxy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CALLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_FILTER_REGISTRY","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_baseExtension","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transferer","type":"address"}],"name":"addLocalContractAllowList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nowPhaseAl","type":"uint256"},{"internalType":"address","name":"_address","type":"address"}],"name":"alIdMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"alMintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"alMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_alId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes32[]","name":"proof_","type":"bytes32[]"}],"name":"allowlistMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enableRestrict","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAlMaxMints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLocalContractAllowList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_alId","type":"uint256"}],"name":"getPhaseIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_candidate","type":"address"}],"name":"grantOperatorRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"isAlSaleEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"address_","type":"address"},{"internalType":"uint256","name":"_alId","type":"uint256"},{"internalType":"bytes32[]","name":"proof_","type":"bytes32[]"}],"name":"isAllowlisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"}],"name":"isOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPublicSaleEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"address_","type":"address"},{"internalType":"uint256","name":"_phaseId","type":"uint256"},{"internalType":"uint256","name":"wlCount","type":"uint256"},{"internalType":"bytes32[]","name":"proof_","type":"bytes32[]"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"isWlSaleEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"maxMintsPerAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMintsPerALOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMintsPerPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMintsPerPSOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nowPhaseAl","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nowPhasePs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nowPhaseWl","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operatorFilteringEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_address","type":"address"}],"name":"ownerMintSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"phaseIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"psMintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"psMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"receiveToDeb","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"transferer","type":"address"}],"name":"removeLocalContractAllowList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revealed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_candidate","type":"address"}],"name":"revokeOperatorRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_alId","type":"uint256"},{"internalType":"uint256","name":"_max","type":"uint256"}],"name":"setAlMaxMints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_alId","type":"uint256"},{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setAlPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_alId","type":"uint256"},{"internalType":"bool","name":"bool_","type":"bool"}],"name":"setAllowlistSaleEnable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newBaseExtension","type":"string"}],"name":"setBaseExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri_","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"calAddress","type":"address"}],"name":"setCAL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"level","type":"uint256"}],"name":"setCALLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint96","name":"_feeNumerator","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri_","type":"string"}],"name":"setHiddenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"bool_","type":"bool"}],"name":"setLockBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxSupply","type":"uint256"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_phaseId","type":"uint256"},{"internalType":"bytes32","name":"merkleRoot_","type":"bytes32"}],"name":"setMerkleRootAlWithId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"merkleRoot_","type":"bytes32"}],"name":"setMerkleRootWl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_phaseId","type":"uint256"},{"internalType":"bytes32","name":"merkleRoot_","type":"bytes32"}],"name":"setMerkleRootWlWithId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintable","type":"uint256"}],"name":"setMintable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nowPhaseAl","type":"uint256"}],"name":"setNowPhaseAl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nowPhasePs","type":"uint256"}],"name":"setNowPhasePs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nowPhaseWl","type":"uint256"}],"name":"setNowPhaseWl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"value","type":"bool"}],"name":"setOperatorFilteringEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_alId","type":"uint256"},{"internalType":"uint256","name":"_phaseId","type":"uint256"}],"name":"setPhaseId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_alId","type":"uint256"},{"internalType":"uint256","name":"_phaseId","type":"uint256"}],"name":"setPhaseIdWithReset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_max","type":"uint256"}],"name":"setPsMaxMints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setPsPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"bool_","type":"bool"}],"name":"setPublicSaleEnable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRevealNum","type":"uint256"}],"name":"setReveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"level","type":"uint256"}],"name":"setTokenCALLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"level","type":"uint256"}],"name":"setWalletCALLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_perc","type":"uint256"}],"name":"setWallet__aa","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_perc","type":"uint256"}],"name":"setWallet__bb","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_perc","type":"uint256"}],"name":"setWallet__cc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_perc","type":"uint256"}],"name":"setWallet__dd","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_perc","type":"uint256"}],"name":"setWallet__ee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_perc","type":"uint256"}],"name":"setWallet__ff","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setWallet__ww","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_phaseId","type":"uint256"},{"internalType":"bool","name":"bool_","type":"bool"}],"name":"setWhitelistSaleEnable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setWlPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenCALLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tryOwnerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"walletCALLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"walletOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_phaseId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"wlcount","type":"uint256"},{"internalType":"bytes32[]","name":"proof_","type":"bytes32[]"}],"name":"whitelistMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"wlMintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"wlMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

600c8054600160ff199182168117909255600f82905560168054909116909117905566b1a2bc2ec500006019556002601c819055601e601d8190555560c06040526005608090815264173539b7b760d91b60a05260349062000062908262000b3b565b506037805461ff0019166101001790553480156200007e575f80fd5b5060405162006d6f38038062006d6f833981016040819052620000a19162000c03565b733cc6cdda760b79bafa08df41ecfa224f810dceb660016040518060400160405280600a81526020016941454220424547494e5360b01b8152506040518060400160405280600381526020016220a2a160e91b815250620001116200010b620005c860201b60201c565b620005cc565b60026200011f838262000b3b565b5060036200012e828262000b3b565b506001600555505060016010556daaeb6d7670e522a718067333cd4e3b1562000276578015620001c957604051633e9f1edf60e11b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e90637d3e3dbe906044015b5f604051808303815f87803b158015620001ac575f80fd5b505af1158015620001bf573d5f803e3d5ffd5b5050505062000276565b6001600160a01b038216156200021a5760405163a0af290360e01b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e9063a0af29039060440162000194565b604051632210724360e11b81523060048201526daaeb6d7670e522a718067333cd4e90634420e486906024015f604051808303815f87803b1580156200025e575f80fd5b505af115801562000271573d5f803e3d5ffd5b505050505b50620002849050336200061b565b6200028f836200061b565b6200029b8383620006bd565b620002a76001620007be565b600980546001600160a01b03191673f2a78c73ffbab6ecc3548acc54b546ace279312e179055620002ec731e0049783f008a0085193e00003d00cd54003c71620007ce565b6200030b734fee7b061c97c9c496b01dbce9cdb10c02f0a0be620007ce565b600a7f584f46c60af19681376031579adb04a2416e54ee5505351c2a8435e3766026ea819055601e7f9fafca4c9c0d5c2cbf85f49fd8ab8212430ce78c2a0cb75b51e0f9c4f9ace0035560147f1dd2f4b94a51cfb409e6e317a497f7cfd9013960a1c723f830c49c05a25f08a58190557f804a3d0621e73505f5f0c57c922f3e57d6b48e175551184eb12f80d7b4a9c7838190557fa952f8c0f40734b22d2328e0f7ff57eeffee78885b9cf2147ff941cc37e1c86e557fb48400cb19cf39e58355a7c9fd856f9b5b7298c53856a6766c6b39755ccafa798190557ff5ddd0b8f160eab91dc4f82b50a485a96cf6ab0bfb38460d73171763afb6d5cf8190557f6fa0adbc19babfec7e85ff6417830cdb284ababb3de438515569d7f3d9b34931556018602090815266b1a2bc2ec500007f999d26de3473317ead3eeaf34ca78057f1439db67b6953469c3c96ce9caf6bd781905566470de4df8200007ff3794665d3af9b6fb6f858b70185898134f96768ef31c325d52e04f0ac195a4d55666a94d74f4300007f2bacf7cca723d030d12aee795132f2c5f2d14ad131f16f3f27eeba3e79d18b8c556658d15e176280007f7a6340a7048c03c55288da75abed74d2ce9194201bafb03be53c0a7cca59149555667c5850872380007f5b650d93b25a5c652bc6f9215f522b521daf6d36977dcec1343c2a8310b869d655668e1bc9bf0400007f2288853b49db4f36075bf4a8cfdae4e5e3b39b7b03937d0a9148b051a6f64c5c55669fdf42f6e480007f33d69b83f8d9644c8360a50d7275bf12a50019a4cd4e17926d0b315da648c58d5560075f527f0aaa0ccf1df0cbc345d3ab7229415a03568bb157ac6e99a99e7acfb410c400f5556040805160608101909152603f808252909162006d3090830139603290620005a9908262000b3b565b50602680546001600160a01b03191633179055602c555062000dd49050565b3390565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381165f9081526017602052604090205460ff16156200064e335b6001600160a01b0316601462000814565b60405160200162000660919062000c80565b60405160208183030381529060405290620006995760405162461bcd60e51b815260040162000690919062000cd8565b60405180910390fd5b506001600160a01b03165f908152601760205260409020805460ff19166001179055565b6127106001600160601b03821611156200072d5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b606482015260840162000690565b6001600160a01b038216620007855760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c696420726563656976657200000000000000604482015260640162000690565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217601455565b620007c933620009d0565b600f55565b620007db600a8262000a3c565b506040516001600160a01b0382169033907fbd0af1fe0a2c1c7bb340c17a284a291138979c8eeb797e176dbd1c415199af3c905f90a350565b60605f6200082483600262000d20565b6200083190600262000d3a565b6001600160401b038111156200084b576200084b62000a9b565b6040519080825280601f01601f19166020018201604052801562000876576020820181803683370190505b509050600360fc1b815f8151811062000893576200089362000d50565b60200101906001600160f81b03191690815f1a905350600f60fb1b81600181518110620008c457620008c462000d50565b60200101906001600160f81b03191690815f1a9053505f620008e884600262000d20565b620008f590600162000d3a565b90505b600181111562000976576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106200092d576200092d62000d50565b1a60f81b82828151811062000946576200094662000d50565b60200101906001600160f81b03191690815f1a90535060049490941c936200096e8162000d64565b9050620008f8565b508315620009c75760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640162000690565b90505b92915050565b6001600160a01b0381165f9081526017602052604090205460ff16620009f6336200063d565b60405160200162000a08919062000d7c565b6040516020818303038152906040529062000a385760405162461bcd60e51b815260040162000690919062000cd8565b5050565b5f620009c7836001600160a01b0384165f81815260018301602052604081205462000a9357508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155620009ca565b505f620009ca565b634e487b7160e01b5f52604160045260245ffd5b600181811c9082168062000ac457607f821691505b60208210810362000ae357634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111562000b36575f81815260208120601f850160051c8101602086101562000b115750805b601f850160051c820191505b8181101562000b325782815560010162000b1d565b5050505b505050565b81516001600160401b0381111562000b575762000b5762000a9b565b62000b6f8162000b68845462000aaf565b8462000ae9565b602080601f83116001811462000ba5575f841562000b8d5750858301515b5f19600386901b1c1916600185901b17855562000b32565b5f85815260208120601f198616915b8281101562000bd55788860151825594840194600190910190840162000bb4565b508582101562000bf357878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f805f6060848603121562000c16575f80fd5b83516001600160a01b038116811462000c2d575f80fd5b60208501519093506001600160601b038116811462000c4a575f80fd5b80925050604084015190509250925092565b5f5b8381101562000c7857818101518382015260200162000c5e565b50505f910152565b67030b1b1b7bab73a160c51b81525f825162000ca481600885016020870162000c5c565b7f20697320616c72656164792068617320616e206f70657261746f7220726f6c656008939091019283015250602801919050565b602081525f825180602084015262000cf881604085016020870162000c5c565b601f01601f19169190910160400192915050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417620009ca57620009ca62000d0c565b80820180821115620009ca57620009ca62000d0c565b634e487b7160e01b5f52603260045260245ffd5b5f8162000d755762000d7562000d0c565b505f190190565b67030b1b1b7bab73a160c51b81525f825162000da081600885016020870162000c5c565b7f206973206e6f7420616e206f70657261746f72000000000000000000000000006008939091019283015250601b01919050565b615f4e8062000de25f395ff3fe608060405260043610610616575f3560e01c806370a082311161031b578063b7c0b8e8116101ae578063df58a1b5116100fd578063f09388891161009d578063fb796e6c11610078578063fb796e6c146112f8578063fe08eab014611311578063fe335dee14611330578063ff7682121461134f575f80fd5b8063f09388891461128c578063f1e9770b146112ba578063f2fde38b146112d9575f80fd5b8063e4848292116100d8578063e484829214611225578063e8a3d48514611244578063e985e9c514611258578063ea7baab114611277575f80fd5b8063df58a1b5146111de578063df725396146111f3578063e0669c5514611206575f80fd5b8063c66eceb511610168578063d5abeb0111610143578063d5abeb0114611176578063d5dcfbc61461118b578063d78be71c146111a0578063da3ef23f146111bf575f80fd5b8063c66eceb514611119578063c87b56dd14611138578063d2de022f14611157575f80fd5b8063b7c0b8e814611050578063b88d4fde1461106f578063b9a2e6551461108e578063ba05e115146110ad578063bbaac02f146110db578063c50c8186146110fa575f80fd5b80638e37326a1161026a578063a22cb46511610224578063b219f7d7116101ff578063b219f7d714610fb9578063b31391cb14610fd8578063b435d23614611003578063b6cbcf3314611025575f80fd5b8063a22cb46514610f50578063a355fd2914610f6f578063a35c23ad14610f8e575f80fd5b80638e37326a14610e6457806391e4bac814610eb4578063942958f414610ed357806395d89b4114610f15578063962c167b14610f295780639da9778c14610f48575f80fd5b8063830b3a64116102d55780638528eefe116102b05780638528eefe14610deb5780638bec504014610e0a5780638da5cb5b14610e295780638dd07d0f14610e45575f80fd5b8063830b3a6414610d98578063830f821114610db75780638462151c14610dcc575f80fd5b806370a0823114610cc6578063715018a614610ce557806372b44d7114610cf957806378a9238014610d185780637c3dc17314610d5a578063813779ef14610d79575f80fd5b80632c3936ce116104ad57806342966c68116103fc5780635822768b1161039c5780636352211e116103775780636352211e14610c325780636d70f7ae14610c515780636f8b44b014610c885780636fa0cf5f14610ca7575f80fd5b80635822768b14610bdf57806358303b1014610bfe5780635b075f3614610c13575f80fd5b80634bf365df116103d75780634bf365df14610b815780634f3db34614610b965780635183022714610bab57806355f804b314610bc0575f80fd5b806342966c6814610b17578063435e4ccd14610b36578063438b630014610b55575f80fd5b8063396e8f531161046757806340505960116104425780634050596014610a9757806341f4343414610ac257806342454db914610ae357806342842e0e14610af8575f80fd5b8063396e8f5314610a575780633ccfd60b14610a765780634009920d14610a7e575f80fd5b80632c3936ce146109bd5780632c4e9fc6146109e85780632d945cb9146109fd5780632db1154414610a105780632e9901f414610a2357806330e7ed3514610a38575f80fd5b806319d580a81161056957806323b872dd1161052357806327ac0c58116104fe57806327ac0c581461092257806327d22615146109415780632a55205a146109605780632c04f0f51461099e575f80fd5b806323b872dd146108d0578063258bc0ef146108ef5780632672c9021461090e575f80fd5b806319d580a8146107d65780631a09cfe2146107f55780631a8b83571461080a5780632143442114610835578063235dfa50146108865780632398f843146108a5575f80fd5b806307265389116105d45780630b8cb103116105af5780630b8cb103146107625780630d9005ae146107815780630f4345e2146107a357806318160ddd146107c2575f80fd5b806307265389146106f3578063081812fc1461070c578063095ea7b314610743575f80fd5b80623f332f1461061a57806301ffc9a714610644578063025e332e1461067357806303c0f48c1461069457806304634d8d146106b357806306fdde03146106d2575b5f80fd5b348015610625575f80fd5b5061062e61136e565b60405161063b9190615270565b60405180910390f35b34801561064f575f80fd5b5061066361065e3660046152d1565b61137d565b604051901515815260200161063b565b34801561067e575f80fd5b5061069261068d366004615300565b61138d565b005b34801561069f575f80fd5b506106926106ae36600461531b565b6113b7565b3480156106be575f80fd5b506106926106cd366004615332565b6113c5565b3480156106dd575f80fd5b506106e66113dc565b60405161063b91906153c1565b3480156106fe575f80fd5b50600c546106639060ff1681565b348015610717575f80fd5b5061072b61072636600461531b565b61146c565b6040516001600160a01b03909116815260200161063b565b34801561074e575f80fd5b5061069261075d3660046153d3565b6114fa565b34801561076d575f80fd5b5061069261077c366004615300565b6115d1565b34801561078c575f80fd5b506107956115fc565b60405190815260200161063b565b3480156107ae575f80fd5b506106926107bd36600461531b565b611612565b3480156107cd575f80fd5b50610795611620565b3480156107e1575f80fd5b506106926107f03660046153d3565b611631565b348015610800575f80fd5b50610795601c5481565b348015610815575f80fd5b5061079561082436600461531b565b601b6020525f908152604090205481565b348015610840575f80fd5b5061079561084f366004615300565b6023545f908152603a602090815260408083206038835281842054845282528083206001600160a01b039094168352929052205490565b348015610891575f80fd5b506106926108a03660046153d3565b611660565b3480156108b0575f80fd5b506107956108bf366004615300565b600e6020525f908152604090205481565b3480156108db575f80fd5b506106926108ea3660046153fd565b61168f565b3480156108fa575f80fd5b5061069261090936600461531b565b611776565b348015610919575f80fd5b506106e6611796565b34801561092d575f80fd5b5061069261093c366004615300565b611822565b34801561094c575f80fd5b5061069261095b3660046153d3565b611833565b34801561096b575f80fd5b5061097f61097a36600461543b565b611862565b604080516001600160a01b03909316835260208301919091520161063b565b3480156109a9575f80fd5b506106926109b836600461543b565b61190c565b3480156109c8575f80fd5b506107956109d736600461531b565b60186020525f908152604090205481565b3480156109f3575f80fd5b50610795601a5481565b610692610a0b36600461551b565b611926565b610692610a1e36600461531b565b611c05565b348015610a2e575f80fd5b50610795601d5481565b348015610a43575f80fd5b50610692610a5236600461531b565b611e3f565b348015610a62575f80fd5b5060095461072b906001600160a01b031681565b610692611e4d565b348015610a89575f80fd5b506037546106639060ff1681565b348015610aa2575f80fd5b50610795610ab136600461531b565b5f9081526038602052604090205490565b348015610acd575f80fd5b5061072b6daaeb6d7670e522a718067333cd4e81565b348015610aee575f80fd5b5061079560195481565b348015610b03575f80fd5b50610692610b123660046153fd565b6127bc565b348015610b22575f80fd5b50610692610b3136600461531b565b612898565b348015610b41575f80fd5b50610692610b50366004615573565b612938565b348015610b60575f80fd5b50610b74610b6f366004615300565b61295b565b60405161063b919061558e565b348015610b8c575f80fd5b5061079560205481565b348015610ba1575f80fd5b50610795600f5481565b348015610bb6575f80fd5b5061079560215481565b348015610bcb575f80fd5b50610692610bda366004615619565b612a8b565b348015610bea575f80fd5b50610692610bf93660046153d3565b612aa0565b348015610c09575f80fd5b5061079560135481565b348015610c1e575f80fd5b50610692610c2d36600461543b565b612acf565b348015610c3d575f80fd5b5061072b610c4c36600461531b565b612b04565b348015610c5c575f80fd5b50610663610c6b366004615300565b6001600160a01b03165f9081526017602052604090205460ff1690565b348015610c93575f80fd5b50610692610ca236600461531b565b612b17565b348015610cb2575f80fd5b50610692610cc136600461543b565b612b25565b348015610cd1575f80fd5b50610795610ce0366004615300565b612b3f565b348015610cf0575f80fd5b50610692612c0c565b348015610d04575f80fd5b50610692610d13366004615300565b612c1d565b348015610d23575f80fd5b50610795610d32366004615300565b6022545f9081526039602090815260408083206001600160a01b039094168352929052205490565b348015610d65575f80fd5b50610692610d7436600461543b565b612c2f565b348015610d84575f80fd5b50610692610d9336600461531b565b612cbe565b348015610da3575f80fd5b5061072b610db236600461531b565b612ccc565b348015610dc2575f80fd5b5061079560225481565b348015610dd7575f80fd5b50610b74610de6366004615300565b612d36565b348015610df6575f80fd5b50610692610e0536600461565d565b612dfa565b348015610e15575f80fd5b50610692610e243660046153d3565b612e22565b348015610e34575f80fd5b505f546001600160a01b031661072b565b348015610e50575f80fd5b50610692610e5f36600461531b565b612e51565b348015610e6f575f80fd5b50610795610e7e366004615680565b5f918252603a602090815260408084206038835281852054855282528084206001600160a01b0393909316845291905290205490565b348015610ebf575f80fd5b50610692610ece36600461531b565b612e5f565b348015610ede575f80fd5b50610795610eed366004615300565b6024545f908152603b602090815260408083206001600160a01b039094168352929052205490565b348015610f20575f80fd5b506106e6612e6d565b348015610f34575f80fd5b50610692610f433660046153d3565b612e7c565b610692612eab565b348015610f5b575f80fd5b50610692610f6a3660046156a3565b612ee5565b348015610f7a575f80fd5b50610692610f89366004615573565b612fb7565b348015610f99575f80fd5b50610692610fa836600461531b565b335f908152600e6020526040902055565b348015610fc4575f80fd5b50610692610fd3366004615300565b612fd3565b348015610fe3575f80fd5b50610795610ff236600461531b565b600d6020525f908152604090205481565b34801561100e575f80fd5b506013545f908152601b6020526040902054610795565b348015611030575f80fd5b5061079561103f36600461531b565b60386020525f908152604090205481565b34801561105b575f80fd5b5061069261106a366004615573565b612fe4565b34801561107a575f80fd5b506106926110893660046156cf565b613000565b348015611099575f80fd5b506106926110a836600461543b565b6130ea565b3480156110b8575f80fd5b506106636110c736600461531b565b60356020525f908152604090205460ff1681565b3480156110e6575f80fd5b506106926110f5366004615619565b613104565b348015611105575f80fd5b5061069261111436600461531b565b613119565b348015611124575f80fd5b5061069261113336600461543b565b613127565b348015611143575f80fd5b506106e661115236600461531b565b613141565b348015611162575f80fd5b50610663611171366004615749565b613274565b348015611181575f80fd5b50610795601f5481565b348015611196575f80fd5b5061079560235481565b3480156111ab575f80fd5b506106926111ba36600461531b565b6133a3565b3480156111ca575f80fd5b506106926111d9366004615619565b6133b1565b3480156111e9575f80fd5b5061079560245481565b610692611201366004615787565b6133c6565b348015611211575f80fd5b5061069261122036600461531b565b61363f565b348015611230575f80fd5b5061069261123f36600461565d565b61364d565b34801561124f575f80fd5b506106e6613675565b348015611263575f80fd5b506106636112723660046157d0565b61367f565b348015611282575f80fd5b50610795601e5481565b348015611297575f80fd5b506106636112a636600461531b565b60366020525f908152604090205460ff1681565b3480156112c5575f80fd5b506106636112d43660046157fc565b6136c9565b3480156112e4575f80fd5b506106926112f3366004615300565b613800565b348015611303575f80fd5b506016546106639060ff1681565b34801561131c575f80fd5b5061069261132b366004615680565b613876565b34801561133b575f80fd5b5061069261134a36600461543b565b6138c7565b34801561135a575f80fd5b50610692611369366004615300565b6138e1565b60606113786138f3565b905090565b5f611387826138ff565b92915050565b61139633613923565b600980546001600160a01b0319166001600160a01b03831617905550565b50565b6113c033613923565b602355565b6113ce33613923565b6113d88282613990565b5050565b6060600280546113eb90615842565b80601f016020809104026020016040519081016040528092919081815260200182805461141790615842565b80156114625780601f1061143957610100808354040283529160200191611462565b820191905f5260205f20905b81548152906001019060200180831161144557829003601f168201915b5050505050905090565b5f61147682613a8d565b6114df5760405162461bcd60e51b815260206004820152602f60248201527f4552433732315073693a20617070726f76656420717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b60648201526084015b60405180910390fd5b505f908152600660205260409020546001600160a01b031690565b816daaeb6d7670e522a718067333cd4e3b1580159061151b575060165460ff165b156115c257604051633185c44d60e21b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015611576573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061159a919061587a565b6115c257604051633b79c77360e21b81526001600160a01b03821660048201526024016114d6565b6115cc8383613ac1565b505050565b6115da33613923565b602580546001600160a01b0319166001600160a01b0392909216919091179055565b5f600161160860055490565b61137891906158a9565b61161b33613923565b600f55565b5f611629613ad5565b611608613b35565b61163a33613923565b602880546001600160a01b0319166001600160a01b039390931692909217909155602e55565b61166933613923565b602a80546001600160a01b0319166001600160a01b039390931692909217909155603055565b826daaeb6d7670e522a718067333cd4e3b158015906116b0575060165460ff165b1561176557336001600160a01b038216036116d5576116d0848484613b45565b611770565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015611722573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611746919061587a565b61176557604051633b79c77360e21b81523360048201526024016114d6565b611770848484613b45565b50505050565b61177f33613923565b6113b4816013545f90815260116020526040902055565b603480546117a390615842565b80601f01602080910402602001604051908101604052809291908181526020018280546117cf90615842565b801561181a5780601f106117f15761010080835404028352916020019161181a565b820191905f5260205f20905b8154815290600101906020018083116117fd57829003601f168201915b505050505081565b61182a613b76565b6113b481613bcf565b61183c33613923565b602780546001600160a01b0319166001600160a01b039390931692909217909155602d55565b5f8281526015602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925282916118d65750604080518082019091526014546001600160a01b0381168252600160a01b90046001600160601b031660208201525b60208101515f90612710906118f4906001600160601b0316876158bc565b6118fe91906158d3565b915196919550909350505050565b61191533613923565b5f9182526011602052604090912055565b61192e613c55565b5f8381526036602052604090205460ff1661198b5760405162461bcd60e51b815260206004820152601760248201527f616c6c6f776c6973744d696e742069732050617573656400000000000000000060448201526064016114d6565b611996338483613274565b6119dd5760405162461bcd60e51b8152602060048201526018602482015277596f7520617265206e6f742077686974656c69737465642160401b60448201526064016114d6565b81601d541015611a425760405162461bcd60e51b815260206004820152602a60248201527f616c6c6f776c6973744d696e743a204f766572206d6178206d696e747320706560448201526972206f6e652074696d6560b01b60648201526084016114d6565b5f838152601b6020526040902054821115611ab05760405162461bcd60e51b815260206004820152602860248201527f616c6c6f776c6973744d696e743a204f766572206d6178206d696e74732070656044820152671c881dd85b1b195d60c21b60648201526084016114d6565b5f838152603a60209081526040808320603883528184205484528252808320338452909152902054611ae39083906158f2565b5f848152601b60205260409020541015611b3f5760405162461bcd60e51b815260206004820152601e60248201527f596f752068617665206e6f2077686974656c6973744d696e74206c656674000060448201526064016114d6565b5f83815260186020526040902054611b589083906158bc565b3414611b765760405162461bcd60e51b81526004016114d690615905565b602054611b81611620565b611b8b90846158f2565b111580611b985750602054155b611bb45760405162461bcd60e51b81526004016114d69061593c565b5f838152603a6020908152604080832060388352818420548452825280832033845290915281208054849290611beb9084906158f2565b90915550611bfb90503383613cae565b6115cc6001601055565b611c0d613c55565b60375460ff16611c565760405162461bcd60e51b81526020600482015260146024820152731c1d589b1a58d35a5b9d081a5cc814185d5cd95960621b60448201526064016114d6565b80601e541015611cb85760405162461bcd60e51b815260206004820152602760248201527f7075626c69634d696e743a204f766572206d6178206d696e747320706572206f6044820152666e652074696d6560c81b60648201526084016114d6565b80601c541015611d185760405162461bcd60e51b815260206004820152602560248201527f7075626c69634d696e743a204f766572206d6178206d696e7473207065722077604482015264185b1b195d60da1b60648201526084016114d6565b6024545f908152603b60209081526040808320338452909152902054611d3f9082906158f2565b601c541015611d905760405162461bcd60e51b815260206004820152601b60248201527f596f752068617665206e6f207075626c69634d696e74206c656674000000000060448201526064016114d6565b80601954611d9e91906158bc565b3414611dbc5760405162461bcd60e51b81526004016114d690615905565b602054611dc7611620565b611dd190836158f2565b111580611dde5750602054155b611dfa5760405162461bcd60e51b81526004016114d69061593c565b6024545f908152603b6020908152604080832033845290915281208054839290611e259084906158f2565b90915550611e3590503382613cae565b6113b46001601055565b611e4833613923565b602455565b611e5633613923565b611e5e613c55565b6026546001600160a01b031615801590611e795750602c5415155b80611e8d57506026546001600160a01b0316155b611ef05760405162461bcd60e51b815260206004820152602e60248201527f706c656173652073657420776974686472617720416464726573735f6161206160448201526d3732103832b931b2b73a30b3b29760911b60648201526084016114d6565b6027546001600160a01b031615801590611f0b5750602d5415155b80611f1f57506027546001600160a01b0316155b611f825760405162461bcd60e51b815260206004820152602e60248201527f706c656173652073657420776974686472617720416464726573735f6262206160448201526d3732103832b931b2b73a30b3b29760911b60648201526084016114d6565b6028546001600160a01b031615801590611f9d5750602e5415155b80611fb157506028546001600160a01b0316155b6120145760405162461bcd60e51b815260206004820152602e60248201527f706c656173652073657420776974686472617720416464726573735f6363206160448201526d3732103832b931b2b73a30b3b29760911b60648201526084016114d6565b6029546001600160a01b03161580159061202f5750602f5415155b8061204357506029546001600160a01b0316155b6120a65760405162461bcd60e51b815260206004820152602e60248201527f706c656173652073657420776974686472617720416464726573735f6464206160448201526d3732103832b931b2b73a30b3b29760911b60648201526084016114d6565b602a546001600160a01b0316158015906120c1575060305415155b806120d55750602a546001600160a01b0316155b6121385760405162461bcd60e51b815260206004820152602e60248201527f706c656173652073657420776974686472617720416464726573735f6565206160448201526d3732103832b931b2b73a30b3b29760911b60648201526084016114d6565b602b546001600160a01b031615801590612153575060315415155b806121675750602b546001600160a01b0316155b6121ca5760405162461bcd60e51b815260206004820152602e60248201527f706c656173652073657420776974686472617720416464726573735f6666206160448201526d3732103832b931b2b73a30b3b29760911b60648201526084016114d6565b60265447905f906001600160a01b03161561229a57602654602c546001600160a01b0390911690612710906121ff90856158bc565b61220991906158d3565b6040515f81818185875af1925050503d805f8114612242576040519150601f19603f3d011682016040523d82523d5f602084013e612247565b606091505b5050809150508061229a5760405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2077697468647261775f6161204574686572000000000060448201526064016114d6565b6027546001600160a01b03161561236657602754602d546001600160a01b0390911690612710906122cb90856158bc565b6122d591906158d3565b6040515f81818185875af1925050503d805f811461230e576040519150601f19603f3d011682016040523d82523d5f602084013e612313565b606091505b505080915050806123665760405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2077697468647261775f6262204574686572000000000060448201526064016114d6565b6028546001600160a01b03161561243257602854602e546001600160a01b03909116906127109061239790856158bc565b6123a191906158d3565b6040515f81818185875af1925050503d805f81146123da576040519150601f19603f3d011682016040523d82523d5f602084013e6123df565b606091505b505080915050806124325760405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2077697468647261775f6363204574686572000000000060448201526064016114d6565b6029546001600160a01b0316156124fe57602954602f546001600160a01b03909116906127109061246390856158bc565b61246d91906158d3565b6040515f81818185875af1925050503d805f81146124a6576040519150601f19603f3d011682016040523d82523d5f602084013e6124ab565b606091505b505080915050806124fe5760405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2077697468647261775f6464204574686572000000000060448201526064016114d6565b602a546001600160a01b0316156125ca57602a546030546001600160a01b03909116906127109061252f90856158bc565b61253991906158d3565b6040515f81818185875af1925050503d805f8114612572576040519150601f19603f3d011682016040523d82523d5f602084013e612577565b606091505b505080915050806125ca5760405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2077697468647261775f6565204574686572000000000060448201526064016114d6565b602b546001600160a01b03161561269657602b546031546001600160a01b0390911690612710906125fb90856158bc565b61260591906158d3565b6040515f81818185875af1925050503d805f811461263e576040519150601f19603f3d011682016040523d82523d5f602084013e612643565b606091505b505080915050806126965760405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2077697468647261775f6666204574686572000000000060448201526064016114d6565b6025544792506001600160a01b031615612704576025546040516001600160a01b039091169083905f81818185875af1925050503d805f81146126f4576040519150601f19603f3d011682016040523d82523d5f602084013e6126f9565b606091505b505080915050612761565b5f546001600160a01b03166001600160a01b0316826040515f6040518083038185875af1925050503d805f8114612756576040519150601f19603f3d011682016040523d82523d5f602084013e61275b565b606091505b50909150505b806127ae5760405162461bcd60e51b815260206004820152601860248201527f4661696c656420746f207769746864726177204574686572000000000000000060448201526064016114d6565b50506127ba6001601055565b565b826daaeb6d7670e522a718067333cd4e3b158015906127dd575060165460ff165b1561288d57336001600160a01b038216036127fd576116d0848484613cc7565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa15801561284a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061286e919061587a565b61288d57604051633b79c77360e21b81523360048201526024016114d6565b611770848484613cc7565b336128a282612b04565b6001600160a01b0316146128eb5760405162461bcd60e51b815260206004820152601060248201526f34b9b73a1037bbb732b9103a37b5b2b760811b60448201526064016114d6565b603754610100900460ff161561292f5760405162461bcd60e51b81526020600482015260096024820152686e6f7420616c6c6f7760b81b60448201526064016114d6565b6113b481613ce1565b61294133613923565b603780549115156101000261ff0019909216919091179055565b60605f61296783612b3f565b90505f816001600160401b038111156129825761298261545b565b6040519080825280602002602001820160405280156129ab578160200160208202803683370190505b5090505f60015b60016129bd60055490565b6129c791906158a9565b811015612a81576040516320c2ce9960e21b815260048101829052309063830b3a6490602401602060405180830381865afa158015612a08573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a2c9190615962565b6001600160a01b0316866001600160a01b031603612a6f57808383612a508161597d565b945081518110612a6257612a62615995565b6020026020010181815250505b80612a798161597d565b9150506129b2565b5090949350505050565b612a9433613923565b60336113d882826159ee565b612aa933613923565b602980546001600160a01b0319166001600160a01b039390931692909217909155602f55565b612ad833613923565b5f8281526038602052604081208290556023805460019290612afb9084906158f2565b90915550505050565b5f80612b0f83613d3c565b509392505050565b612b2033613923565b601f55565b612b2e33613923565b5f9182526012602052604090912055565b5f6001600160a01b038216612bac5760405162461bcd60e51b815260206004820152602d60248201527f4552433732315073693a2062616c616e636520717565727920666f722074686560448201526c207a65726f206164647265737360981b60648201526084016114d6565b5f60015b600554811015612c0557612bc381613a8d565b15612bf557612bd181612b04565b6001600160a01b0316846001600160a01b031603612bf557612bf28261597d565b91505b612bfe8161597d565b9050612bb0565b5092915050565b612c14613b76565b6127ba5f613dd1565b612c2633613923565b6113b481613e20565b81612c3981612b04565b6001600160a01b0316336001600160a01b031614612cac5760405162461bcd60e51b815260206004820152602a60248201527f5265737472696374417070726f76653a206f7065726174696f6e206973206f6e604482015269363c903437b63232b91760b11b60648201526084016114d6565b505f918252600d602052604090912055565b612cc733613923565b601c55565b6040516331a9108f60e11b8152600481018290525f903090636352211e90602401602060405180830381865afa925050508015612d26575060408051601f3d908101601f19168201909252612d2391810190615962565b60015b61138757505f919050565b919050565b60605f80612d4384612b3f565b90505f816001600160401b03811115612d5e57612d5e61545b565b604051908082528060200260200182016040528015612d87578160200160208202803683370190505b50905060015b828414612df157612d9d81613a8d565b15612de957856001600160a01b0316612db582612b04565b6001600160a01b031603612de95780828580600101965081518110612ddc57612ddc615995565b6020026020010181815250505b600101612d8d565b50949350505050565b612e0333613923565b5f91825260366020526040909120805460ff1916911515919091179055565b612e2b33613923565b602680546001600160a01b0319166001600160a01b039390931692909217909155602c55565b612e5a33613923565b601a55565b612e6833613923565b602055565b6060600380546113eb90615842565b612e8533613923565b602b80546001600160a01b0319166001600160a01b039390931692909217909155603155565b612eb433613923565b612ebc613c55565b5f3411612edb5760405162461bcd60e51b81526004016114d690615905565b6127ba6001601055565b816daaeb6d7670e522a718067333cd4e3b15801590612f06575060165460ff165b15612fad57604051633185c44d60e21b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015612f61573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f85919061587a565b612fad57604051633b79c77360e21b81526001600160a01b03821660048201526024016114d6565b6115cc8383613e64565b612fc033613923565b6037805460ff1916911515919091179055565b612fdb613b76565b6113b481613ee2565b612fed33613923565b6016805460ff1916911515919091179055565b836daaeb6d7670e522a718067333cd4e3b15801590613021575060165460ff165b156130d757336001600160a01b038216036130475761304285858585613f0b565b6130e3565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015613094573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130b8919061587a565b6130d757604051633b79c77360e21b81523360048201526024016114d6565b6130e385858585613f0b565b5050505050565b6130f333613923565b5f918252601b602052604090912055565b61310d33613923565b60326113d882826159ee565b61312233613923565b602155565b61313033613923565b5f9182526018602052604090912055565b606061314c82613a8d565b6131985760405162461bcd60e51b815260206004820152601f60248201527f55524920717565727920666f72206e6f6e6578697374656e7420746f6b656e0060448201526064016114d6565b6131a482602154101590565b156131e4576131b1613f3d565b6131ba83613f4c565b60346040516020016131ce93929190615aa9565b6040516020818303038152906040529050919050565b603280546131f190615842565b80601f016020809104026020016040519081016040528092919081815260200182805461321d90615842565b80156132685780601f1061323f57610100808354040283529160200191613268565b820191905f5260205f20905b81548152906001019060200180831161324b57829003601f168201915b50505050509050919050565b6040516bffffffffffffffffffffffff19606085901b1660208201525f9081906034016040516020818303038152906040528051906020012090505f5b835181101561338a578381815181106132cc576132cc615995565b6020026020010151821061332a578381815181106132ec576132ec615995565b60200260200101518260405160200161330f929190918252602082015260400190565b60405160208183030381529060405280519060200120613376565b8184828151811061333d5761333d615995565b602002602001015160405160200161335f929190918252602082015260400190565b604051602081830303815290604052805190602001205b9150806133828161597d565b9150506132b1565b505f848152601260205260409020541490509392505050565b6133ac33613923565b601955565b6133ba33613923565b60346113d882826159ee565b6133ce613c55565b5f8481526035602052604090205460ff1661342b5760405162461bcd60e51b815260206004820152601760248201527f77686974656c6973744d696e742069732050617573656400000000000000000060448201526064016114d6565b613437338584846136c9565b61347e5760405162461bcd60e51b8152602060048201526018602482015277596f7520617265206e6f742077686974656c69737465642160401b60448201526064016114d6565b5f82116134bf5760405162461bcd60e51b815260206004820152600f60248201526e596f752068617665206e6f20574c2160881b60448201526064016114d6565b828210156135205760405162461bcd60e51b815260206004820152602860248201527f77686974656c6973744d696e743a204f766572206d6178206d696e74732070656044820152671c881dd85b1b195d60c21b60648201526084016114d6565b5f8481526039602090815260408083203384529091529020546135449084906158f2565b8210156135935760405162461bcd60e51b815260206004820152601e60248201527f596f752068617665206e6f2077686974656c6973744d696e74206c656674000060448201526064016114d6565b82601a546135a191906158bc565b34146135bf5760405162461bcd60e51b81526004016114d690615905565b6020546135ca611620565b6135d490856158f2565b1115806135e15750602054155b6135fd5760405162461bcd60e51b81526004016114d69061593c565b5f848152603960209081526040808320338452909152812080548592906136259084906158f2565b9091555061363590503384613cae565b6117706001601055565b61364833613923565b602255565b61365633613923565b5f91825260356020526040909120805460ff1916911515919091179055565b6060611378613fdb565b5f61368a838361405a565b15155f0361369957505f611387565b6001600160a01b038084165f9081526007602090815260408083209386168352929052205460ff165b9392505050565b6040516bffffffffffffffffffffffff19606086901b166020820152603481018390525f9081906054016040516020818303038152906040528051906020012090505f5b83518110156137e65783818151811061372857613728615995565b602002602001015182106137865783818151811061374857613748615995565b60200260200101518260405160200161376b929190918252602082015260400190565b604051602081830303815290604052805190602001206137d2565b8184828151811061379957613799615995565b60200260200101516040516020016137bb929190918252602082015260400190565b604051602081830303815290604052805190602001205b9150806137de8161597d565b91505061370d565b505f85815260116020526040902054149050949350505050565b613808613b76565b6001600160a01b03811661386d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016114d6565b6113b481613dd1565b61387f33613923565b601f5461388a611620565b61389490846158f2565b1115806138a15750601f54155b6138bd5760405162461bcd60e51b81526004016114d69061593c565b6113d88183613cae565b6138d033613923565b5f9182526038602052604090912055565b6138ea33613923565b6113b481614079565b6060611378600a6140bd565b5f6001600160e01b0319821663152a902d60e11b14806113875750611387826140c9565b6001600160a01b0381165f9081526017602052604090205460ff16613953335b6001600160a01b031660146140ed565b6040516020016139639190615b44565b604051602081830303815290604052906113d85760405162461bcd60e51b81526004016114d691906153c1565b6127106001600160601b03821611156139fe5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b60648201526084016114d6565b6001600160a01b038216613a545760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c69642072656365697665720000000000000060448201526064016114d6565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217601455565b600881811c5f9081526020919091526040812054600160ff1b60ff84161c1615613ab857505f919050565b61138782614282565b613acb828261429d565b6113d88282614318565b6005545f9081908190613aec9060081c60016158f2565b9050815b81811015613b2f575f81815260086020526040902054613b0f81614429565b613b1990866158f2565b9450508080613b279061597d565b915050613af0565b50505090565b5f600160055461137891906158a9565b613b4f3382614441565b613b6b5760405162461bcd60e51b81526004016114d690615b90565b6115cc838383614504565b5f546001600160a01b031633146127ba5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016114d6565b6001600160a01b0381165f9081526017602052604090205460ff1615613bf433613943565b604051602001613c049190615be4565b60405160208183030381529060405290613c315760405162461bcd60e51b81526004016114d691906153c1565b506001600160a01b03165f908152601760205260409020805460ff19166001179055565b600260105403613ca75760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016114d6565b6002601055565b6113d8828260405180602001604052805f8152506146f8565b6115cc83838360405180602001604052805f815250613000565b5f613ceb82612b04565b9050613cf8600883614737565b60405182905f906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a46113d8815f846001614762565b5f80613d4783613a8d565b613da85760405162461bcd60e51b815260206004820152602c60248201527f4552433732315073693a206f776e657220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084016114d6565b613db183614784565b5f818152600460205260409020546001600160a01b031694909350915050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b613e2b600a82614790565b506040516001600160a01b0382169033907f3b01c97343869ca2757fcc37cdb8f71683b0a7aed858e3755f4529a1db857292905f90a350565b613e6d826147a4565b80613e76575080155b613ed85760405162461bcd60e51b815260206004820152602d60248201527f5265737472696374417070726f76653a2043616e206e6f7420617070726f766560448201526c103637b1b5b2b2103a37b5b2b760991b60648201526084016114d6565b6113d882826147af565b613eeb81613923565b6001600160a01b03165f908152601760205260409020805460ff19169055565b613f153383614441565b613f315760405162461bcd60e51b81526004016114d690615b90565b61177084848484614872565b6060603380546113eb90615842565b60605f613f588361488b565b60010190505f816001600160401b03811115613f7657613f7661545b565b6040519080825280601f01601f191660200182016040528015613fa0576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084613faa57509392505050565b60605f80613feb81612710611862565b91509150614034613ffb82613f4c565b61400f846001600160a01b031660146140ed565b604051602001614020929190615c3a565b604051602081830303815290604052614962565b6040516020016140449190615cbf565b6040516020818303038152906040529250505090565b5f8061406584614ac0565b90506140718382614b00565b949350505050565b614084600a82614b96565b506040516001600160a01b0382169033907fbd0af1fe0a2c1c7bb340c17a284a291138979c8eeb797e176dbd1c415199af3c905f90a350565b60605f6136c283614baa565b5f6001600160e01b03198216630101c11560e71b1480611387575061138782614c02565b60605f6140fb8360026158bc565b6141069060026158f2565b6001600160401b0381111561411d5761411d61545b565b6040519080825280601f01601f191660200182016040528015614147576020820181803683370190505b509050600360fc1b815f8151811061416157614161615995565b60200101906001600160f81b03191690815f1a905350600f60fb1b8160018151811061418f5761418f615995565b60200101906001600160f81b03191690815f1a9053505f6141b18460026158bc565b6141bc9060016158f2565b90505b6001811115614233576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106141f0576141f0615995565b1a60f81b82828151811061420657614206615995565b60200101906001600160f81b03191690815f1a90535060049490941c9361422c81615d03565b90506141bf565b5083156136c25760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016114d6565b5f61428c60055490565b821080156113875750506001111590565b6001600160a01b038216156113d8576142b68183614c51565b6113d85760405162461bcd60e51b815260206004820152602d60248201527f5265737472696374417070726f76653a2054686520636f6e747261637420697360448201526c103737ba1030b63637bbb2b21760991b60648201526084016114d6565b5f61432282612b04565b9050806001600160a01b0316836001600160a01b0316036143915760405162461bcd60e51b8152602060048201526024808201527f4552433732315073693a20617070726f76616c20746f2063757272656e74206f6044820152633bb732b960e11b60648201526084016114d6565b336001600160a01b03821614806143ad57506143ad813361367f565b61441f5760405162461bcd60e51b815260206004820152603b60248201527f4552433732315073693a20617070726f76652063616c6c6572206973206e6f7460448201527f206f776e6572206e6f7220617070726f76656420666f7220616c6c000000000060648201526084016114d6565b6115cc8383614c5d565b5f5b8115612d31575f1982019091169060010161442b565b5f61444b82613a8d565b6144af5760405162461bcd60e51b815260206004820152602f60248201527f4552433732315073693a206f70657261746f7220717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b60648201526084016114d6565b5f6144b983612b04565b9050806001600160a01b0316846001600160a01b031614806144f45750836001600160a01b03166144e98461146c565b6001600160a01b0316145b806140715750614071818561367f565b5f8061450f83613d3c565b91509150846001600160a01b0316826001600160a01b0316146145895760405162461bcd60e51b815260206004820152602c60248201527f4552433732315073693a207472616e73666572206f6620746f6b656e2074686160448201526b3a1034b9903737ba1037bbb760a11b60648201526084016114d6565b6001600160a01b0384166145ef5760405162461bcd60e51b815260206004820152602760248201527f4552433732315073693a207472616e7366657220746f20746865207a65726f206044820152666164647265737360c81b60648201526084016114d6565b6145f95f84614c5d565b5f6146058460016158f2565b600881901c5f90815260016020526040902054909150600160ff1b60ff83161c16158015614634575060055481105b1561466a575f81815260046020526040902080546001600160a01b0319166001600160a01b03881617905561466a600182614737565b5f84815260046020526040902080546001600160a01b0319166001600160a01b0387161790558184146146a2576146a2600185614737565b83856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46146f08686866001614762565b505050505050565b5f61470260055490565b905061470e8484614cca565b61471b5f85838686614e44565b6117705760405162461bcd60e51b81526004016114d690615d18565b600881901c5f90815260209290925260409091208054600160ff1b60ff9093169290921c9091179055565b6001600160a01b03841615611770575f828152600d6020526040812055611770565b5f611387600183614f77565b5f6136c2836001600160a01b03841661506b565b5f611387338361405a565b336001600160a01b038316036148075760405162461bcd60e51b815260206004820152601c60248201527f4552433732315073693a20617070726f766520746f2063616c6c65720000000060448201526064016114d6565b335f8181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61487d848484614504565b61471b848484600185614e44565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106148c95772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106148f5576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061491357662386f26fc10000830492506010015b6305f5e100831061492b576305f5e100830492506008015b612710831061493f57612710830492506004015b60648310614951576064830492506002015b600a83106113875760010192915050565b606081515f0361497f57505060408051602081019091525f815290565b5f604051806060016040528060408152602001615dd96040913990505f6003845160026149ac91906158f2565b6149b691906158d3565b6149c19060046158bc565b90505f6149cf8260206158f2565b6001600160401b038111156149e6576149e661545b565b6040519080825280601f01601f191660200182016040528015614a10576020820181803683370190505b509050818152600183018586518101602084015b81831015614a7c576003830192508251603f8160121c168501518253600182019150603f81600c1c168501518253600182019150603f8160061c168501518253600182019150603f8116850151825350600101614a24565b600389510660018114614a965760028114614aa757614ab2565b613d3d60f01b600119830152614ab2565b603d60f81b5f198301525b509398975050505050505050565b6001600160a01b0381165f908152600e602052604081205415614af857506001600160a01b03165f908152600e602052604090205490565b5050600f5490565b600c545f9060ff16614b1457506001611387565b614b1d8361514e565b806136c25750600954604051630f8350ed60e41b81526001600160a01b038581166004830152602482018590529091169063f8350ed090604401602060405180830381865afa158015614b72573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136c2919061587a565b5f6136c2836001600160a01b038416615176565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561326857602002820191905f5260205f20905b815481526020019060010190808311614be35750505050509050919050565b5f6001600160e01b031982166380ac58cd60e01b1480614c3257506001600160e01b03198216635b5e139f60e01b145b8061138757506301ffc9a760e01b6001600160e01b0319831614611387565b5f8061406533856151c2565b5f81815260066020526040902080546001600160a01b0319166001600160a01b0384169081179091558190614c9182612b04565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b5f614cd460055490565b90505f8211614d335760405162461bcd60e51b815260206004820152602560248201527f4552433732315073693a207175616e74697479206d7573742062652067726561604482015264074657220360dc1b60648201526084016114d6565b6001600160a01b038316614d955760405162461bcd60e51b815260206004820152602360248201527f4552433732315073693a206d696e7420746f20746865207a65726f206164647260448201526265737360e81b60648201526084016114d6565b8160055f828254614da691906158f2565b90915550505f81815260046020526040902080546001600160a01b0319166001600160a01b038516179055614ddc600182614737565b614de85f848385614762565b805b614df483836158f2565b8110156117705760405181906001600160a01b038616905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a480614e3c8161597d565b915050614dea565b5f6001600160a01b0385163b15614f6a57506001835b614e6484866158f2565b811015614f6457604051630a85bd0160e11b81526001600160a01b0387169063150b7a0290614e9d9033908b9086908990600401615d6d565b6020604051808303815f875af1925050508015614ed7575060408051601f3d908101601f19168201909252614ed491810190615da9565b60015b614f32573d808015614f04576040519150601f19603f3d011682016040523d82523d5f602084013e614f09565b606091505b5080515f03614f2a5760405162461bcd60e51b81526004016114d690615d18565b805181602001fd5b828015614f4f57506001600160e01b03198116630a85bd0160e11b145b92505080614f5c8161597d565b915050614e5a565b50614f6e565b5060015b95945050505050565b600881901c5f8181526020849052604081205490919060ff808516919082181c8015614fb857614fa6816151f2565b60ff168203600884901b179350615062565b5f83116150245760405162461bcd60e51b815260206004820152603460248201527f4269744d6170733a205468652073657420626974206265666f7265207468652060448201527334b73232bc103237b2b9b713ba1032bc34b9ba1760611b60648201526084016114d6565b505f199091015f81815260208690526040902054909190801561505d5761504a816151f2565b60ff0360ff16600884901b179350615062565b614fb8565b50505092915050565b5f8181526001830160205260408120548015615145575f61508d6001836158a9565b85549091505f906150a0906001906158a9565b90508181146150ff575f865f0182815481106150be576150be615995565b905f5260205f200154905080875f0184815481106150de576150de615995565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061511057615110615dc4565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050611387565b5f915050611387565b5f611387600a836001600160a01b0381165f90815260018301602052604081205415156136c2565b5f8181526001830160205260408120546151bb57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155611387565b505f611387565b5f818152600d6020526040812054156151e957505f818152600d6020526040902054611387565b6136c283614ac0565b5f6040518061012001604052806101008152602001615e19610100913960f87e818283848586878898a8b8c8d8e8f929395969799a9b9d9e9faaeb6bedeeff61523a8561525b565b02901c8151811061524d5761524d615995565b016020015160f81c92915050565b5f808211615267575f80fd5b505f8190031690565b602080825282518282018190525f9190848201906040850190845b818110156152b05783516001600160a01b03168352928401929184019160010161528b565b50909695505050505050565b6001600160e01b0319811681146113b4575f80fd5b5f602082840312156152e1575f80fd5b81356136c2816152bc565b6001600160a01b03811681146113b4575f80fd5b5f60208284031215615310575f80fd5b81356136c2816152ec565b5f6020828403121561532b575f80fd5b5035919050565b5f8060408385031215615343575f80fd5b823561534e816152ec565b915060208301356001600160601b0381168114615369575f80fd5b809150509250929050565b5f5b8381101561538e578181015183820152602001615376565b50505f910152565b5f81518084526153ad816020860160208601615374565b601f01601f19169290920160200192915050565b602081525f6136c26020830184615396565b5f80604083850312156153e4575f80fd5b82356153ef816152ec565b946020939093013593505050565b5f805f6060848603121561540f575f80fd5b833561541a816152ec565b9250602084013561542a816152ec565b929592945050506040919091013590565b5f806040838503121561544c575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156154975761549761545b565b604052919050565b5f82601f8301126154ae575f80fd5b813560206001600160401b038211156154c9576154c961545b565b8160051b6154d882820161546f565b92835284810182019282810190878511156154f1575f80fd5b83870192505b84831015615510578235825291830191908301906154f7565b979650505050505050565b5f805f6060848603121561552d575f80fd5b833592506020840135915060408401356001600160401b03811115615550575f80fd5b61555c8682870161549f565b9150509250925092565b80151581146113b4575f80fd5b5f60208284031215615583575f80fd5b81356136c281615566565b602080825282518282018190525f9190848201906040850190845b818110156152b0578351835292840192918401916001016155a9565b5f6001600160401b038311156155dd576155dd61545b565b6155f0601f8401601f191660200161546f565b9050828152838383011115615603575f80fd5b828260208301375f602084830101529392505050565b5f60208284031215615629575f80fd5b81356001600160401b0381111561563e575f80fd5b8201601f8101841361564e575f80fd5b614071848235602084016155c5565b5f806040838503121561566e575f80fd5b82359150602083013561536981615566565b5f8060408385031215615691575f80fd5b823591506020830135615369816152ec565b5f80604083850312156156b4575f80fd5b82356156bf816152ec565b9150602083013561536981615566565b5f805f80608085870312156156e2575f80fd5b84356156ed816152ec565b935060208501356156fd816152ec565b92506040850135915060608501356001600160401b0381111561571e575f80fd5b8501601f8101871361572e575f80fd5b61573d878235602084016155c5565b91505092959194509250565b5f805f6060848603121561575b575f80fd5b8335615766816152ec565b92506020840135915060408401356001600160401b03811115615550575f80fd5b5f805f806080858703121561579a575f80fd5b84359350602085013592506040850135915060608501356001600160401b038111156157c4575f80fd5b61573d8782880161549f565b5f80604083850312156157e1575f80fd5b82356157ec816152ec565b91506020830135615369816152ec565b5f805f806080858703121561580f575f80fd5b843561581a816152ec565b9350602085013592506040850135915060608501356001600160401b038111156157c4575f80fd5b600181811c9082168061585657607f821691505b60208210810361587457634e487b7160e01b5f52602260045260245ffd5b50919050565b5f6020828403121561588a575f80fd5b81516136c281615566565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561138757611387615895565b808202811582820484141761138757611387615895565b5f826158ed57634e487b7160e01b5f52601260045260245ffd5b500490565b8082018082111561138757611387615895565b60208082526018908201527f4554482076616c7565206973206e6f7420636f72726563740000000000000000604082015260600190565b6020808252600c908201526b4e6f206d6f7265204e46547360a01b604082015260600190565b5f60208284031215615972575f80fd5b81516136c2816152ec565b5f6001820161598e5761598e615895565b5060010190565b634e487b7160e01b5f52603260045260245ffd5b601f8211156115cc575f81815260208120601f850160051c810160208610156159cf5750805b601f850160051c820191505b818110156146f0578281556001016159db565b81516001600160401b03811115615a0757615a0761545b565b615a1b81615a158454615842565b846159a9565b602080601f831160018114615a4e575f8415615a375750858301515b5f19600386901b1c1916600185901b1785556146f0565b5f85815260208120601f198616915b82811015615a7c57888601518255948401946001909101908401615a5d565b5085821015615a9957878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f84516020615abb8285838a01615374565b855191840191615ace8184848a01615374565b85549201915f90615ade81615842565b60018281168015615af65760018114615b0b57615b34565b60ff1984168752821515830287019450615b34565b895f52855f205f5b84811015615b2c57815489820152908301908701615b13565b505082870194505b50929a9950505050505050505050565b67030b1b1b7bab73a160c51b81525f8251615b66816008850160208701615374565b721034b9903737ba1030b71037b832b930ba37b960691b6008939091019283015250601b01919050565b60208082526034908201527f4552433732315073693a207472616e736665722063616c6c6572206973206e6f6040820152731d081bdddb995c881b9bdc88185c1c1c9bdd995960621b606082015260800190565b67030b1b1b7bab73a160c51b81525f8251615c06816008850160208701615374565b7f20697320616c72656164792068617320616e206f70657261746f7220726f6c656008939091019283015250602801919050565b7f7b2273656c6c65725f6665655f62617369735f706f696e7473223a000000000081525f8351615c7181601b850160208801615374565b721610113332b2afb932b1b4b834b2b73a111d1160691b601b918401918201528351615ca481602e840160208801615374565b61227d60f01b602e9290910191820152603001949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081525f8251615cf681601d850160208701615374565b91909101601d0192915050565b5f81615d1157615d11615895565b505f190190565b60208082526035908201527f4552433732315073693a207472616e7366657220746f206e6f6e20455243373260408201527418a932b1b2b4bb32b91034b6b83632b6b2b73a32b960591b606082015260800190565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f90615d9f90830184615396565b9695505050505050565b5f60208284031215615db9575f80fd5b81516136c2816152bc565b634e487b7160e01b5f52603160045260245ffdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f0001020903110a19042112290b311a3905412245134d2a550c5d32651b6d3a7506264262237d468514804e8d2b95569d0d495ea533a966b11c886eb93bc176c9071727374353637324837e9b47af86c7155181ad4fd18ed32c9096db57d59ee30e2e4a6a5f92a6be3498aae067ddb2eb1d5989b56fd7baf33ca0c2ee77e5caf7ff0810182028303840444c545c646c7425617c847f8c949c48a4a8b087b8c0c816365272829aaec650acd0d28fdad4e22d6991bd97dfdcea58b4d6f29fede4f6fe0f1f2f3f4b5b6b607b8b93a3a7b7bf357199c5abcfd9e168bcdee9b3f1ecf5fd1e3e5a7a8aa2b670c4ced8bbe8f0f4fc3d79a1c3cde7effb78cce6facbf9f8a2646970667358221220df1a468af855e4daf5b4dd55626c27bcd477128fac9099d0973f297784be571364736f6c6343000815003368747470733a2f2f617277656176652e6e65742f515143536739463169363379415575374e524c54356e6376444533484372714678706c364b3869626f683400000000000000000000000027d2210a381e7d5921fbb4df6fa39fd875cecb5700000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000005dc

Deployed Bytecode

0x608060405260043610610616575f3560e01c806370a082311161031b578063b7c0b8e8116101ae578063df58a1b5116100fd578063f09388891161009d578063fb796e6c11610078578063fb796e6c146112f8578063fe08eab014611311578063fe335dee14611330578063ff7682121461134f575f80fd5b8063f09388891461128c578063f1e9770b146112ba578063f2fde38b146112d9575f80fd5b8063e4848292116100d8578063e484829214611225578063e8a3d48514611244578063e985e9c514611258578063ea7baab114611277575f80fd5b8063df58a1b5146111de578063df725396146111f3578063e0669c5514611206575f80fd5b8063c66eceb511610168578063d5abeb0111610143578063d5abeb0114611176578063d5dcfbc61461118b578063d78be71c146111a0578063da3ef23f146111bf575f80fd5b8063c66eceb514611119578063c87b56dd14611138578063d2de022f14611157575f80fd5b8063b7c0b8e814611050578063b88d4fde1461106f578063b9a2e6551461108e578063ba05e115146110ad578063bbaac02f146110db578063c50c8186146110fa575f80fd5b80638e37326a1161026a578063a22cb46511610224578063b219f7d7116101ff578063b219f7d714610fb9578063b31391cb14610fd8578063b435d23614611003578063b6cbcf3314611025575f80fd5b8063a22cb46514610f50578063a355fd2914610f6f578063a35c23ad14610f8e575f80fd5b80638e37326a14610e6457806391e4bac814610eb4578063942958f414610ed357806395d89b4114610f15578063962c167b14610f295780639da9778c14610f48575f80fd5b8063830b3a64116102d55780638528eefe116102b05780638528eefe14610deb5780638bec504014610e0a5780638da5cb5b14610e295780638dd07d0f14610e45575f80fd5b8063830b3a6414610d98578063830f821114610db75780638462151c14610dcc575f80fd5b806370a0823114610cc6578063715018a614610ce557806372b44d7114610cf957806378a9238014610d185780637c3dc17314610d5a578063813779ef14610d79575f80fd5b80632c3936ce116104ad57806342966c68116103fc5780635822768b1161039c5780636352211e116103775780636352211e14610c325780636d70f7ae14610c515780636f8b44b014610c885780636fa0cf5f14610ca7575f80fd5b80635822768b14610bdf57806358303b1014610bfe5780635b075f3614610c13575f80fd5b80634bf365df116103d75780634bf365df14610b815780634f3db34614610b965780635183022714610bab57806355f804b314610bc0575f80fd5b806342966c6814610b17578063435e4ccd14610b36578063438b630014610b55575f80fd5b8063396e8f531161046757806340505960116104425780634050596014610a9757806341f4343414610ac257806342454db914610ae357806342842e0e14610af8575f80fd5b8063396e8f5314610a575780633ccfd60b14610a765780634009920d14610a7e575f80fd5b80632c3936ce146109bd5780632c4e9fc6146109e85780632d945cb9146109fd5780632db1154414610a105780632e9901f414610a2357806330e7ed3514610a38575f80fd5b806319d580a81161056957806323b872dd1161052357806327ac0c58116104fe57806327ac0c581461092257806327d22615146109415780632a55205a146109605780632c04f0f51461099e575f80fd5b806323b872dd146108d0578063258bc0ef146108ef5780632672c9021461090e575f80fd5b806319d580a8146107d65780631a09cfe2146107f55780631a8b83571461080a5780632143442114610835578063235dfa50146108865780632398f843146108a5575f80fd5b806307265389116105d45780630b8cb103116105af5780630b8cb103146107625780630d9005ae146107815780630f4345e2146107a357806318160ddd146107c2575f80fd5b806307265389146106f3578063081812fc1461070c578063095ea7b314610743575f80fd5b80623f332f1461061a57806301ffc9a714610644578063025e332e1461067357806303c0f48c1461069457806304634d8d146106b357806306fdde03146106d2575b5f80fd5b348015610625575f80fd5b5061062e61136e565b60405161063b9190615270565b60405180910390f35b34801561064f575f80fd5b5061066361065e3660046152d1565b61137d565b604051901515815260200161063b565b34801561067e575f80fd5b5061069261068d366004615300565b61138d565b005b34801561069f575f80fd5b506106926106ae36600461531b565b6113b7565b3480156106be575f80fd5b506106926106cd366004615332565b6113c5565b3480156106dd575f80fd5b506106e66113dc565b60405161063b91906153c1565b3480156106fe575f80fd5b50600c546106639060ff1681565b348015610717575f80fd5b5061072b61072636600461531b565b61146c565b6040516001600160a01b03909116815260200161063b565b34801561074e575f80fd5b5061069261075d3660046153d3565b6114fa565b34801561076d575f80fd5b5061069261077c366004615300565b6115d1565b34801561078c575f80fd5b506107956115fc565b60405190815260200161063b565b3480156107ae575f80fd5b506106926107bd36600461531b565b611612565b3480156107cd575f80fd5b50610795611620565b3480156107e1575f80fd5b506106926107f03660046153d3565b611631565b348015610800575f80fd5b50610795601c5481565b348015610815575f80fd5b5061079561082436600461531b565b601b6020525f908152604090205481565b348015610840575f80fd5b5061079561084f366004615300565b6023545f908152603a602090815260408083206038835281842054845282528083206001600160a01b039094168352929052205490565b348015610891575f80fd5b506106926108a03660046153d3565b611660565b3480156108b0575f80fd5b506107956108bf366004615300565b600e6020525f908152604090205481565b3480156108db575f80fd5b506106926108ea3660046153fd565b61168f565b3480156108fa575f80fd5b5061069261090936600461531b565b611776565b348015610919575f80fd5b506106e6611796565b34801561092d575f80fd5b5061069261093c366004615300565b611822565b34801561094c575f80fd5b5061069261095b3660046153d3565b611833565b34801561096b575f80fd5b5061097f61097a36600461543b565b611862565b604080516001600160a01b03909316835260208301919091520161063b565b3480156109a9575f80fd5b506106926109b836600461543b565b61190c565b3480156109c8575f80fd5b506107956109d736600461531b565b60186020525f908152604090205481565b3480156109f3575f80fd5b50610795601a5481565b610692610a0b36600461551b565b611926565b610692610a1e36600461531b565b611c05565b348015610a2e575f80fd5b50610795601d5481565b348015610a43575f80fd5b50610692610a5236600461531b565b611e3f565b348015610a62575f80fd5b5060095461072b906001600160a01b031681565b610692611e4d565b348015610a89575f80fd5b506037546106639060ff1681565b348015610aa2575f80fd5b50610795610ab136600461531b565b5f9081526038602052604090205490565b348015610acd575f80fd5b5061072b6daaeb6d7670e522a718067333cd4e81565b348015610aee575f80fd5b5061079560195481565b348015610b03575f80fd5b50610692610b123660046153fd565b6127bc565b348015610b22575f80fd5b50610692610b3136600461531b565b612898565b348015610b41575f80fd5b50610692610b50366004615573565b612938565b348015610b60575f80fd5b50610b74610b6f366004615300565b61295b565b60405161063b919061558e565b348015610b8c575f80fd5b5061079560205481565b348015610ba1575f80fd5b50610795600f5481565b348015610bb6575f80fd5b5061079560215481565b348015610bcb575f80fd5b50610692610bda366004615619565b612a8b565b348015610bea575f80fd5b50610692610bf93660046153d3565b612aa0565b348015610c09575f80fd5b5061079560135481565b348015610c1e575f80fd5b50610692610c2d36600461543b565b612acf565b348015610c3d575f80fd5b5061072b610c4c36600461531b565b612b04565b348015610c5c575f80fd5b50610663610c6b366004615300565b6001600160a01b03165f9081526017602052604090205460ff1690565b348015610c93575f80fd5b50610692610ca236600461531b565b612b17565b348015610cb2575f80fd5b50610692610cc136600461543b565b612b25565b348015610cd1575f80fd5b50610795610ce0366004615300565b612b3f565b348015610cf0575f80fd5b50610692612c0c565b348015610d04575f80fd5b50610692610d13366004615300565b612c1d565b348015610d23575f80fd5b50610795610d32366004615300565b6022545f9081526039602090815260408083206001600160a01b039094168352929052205490565b348015610d65575f80fd5b50610692610d7436600461543b565b612c2f565b348015610d84575f80fd5b50610692610d9336600461531b565b612cbe565b348015610da3575f80fd5b5061072b610db236600461531b565b612ccc565b348015610dc2575f80fd5b5061079560225481565b348015610dd7575f80fd5b50610b74610de6366004615300565b612d36565b348015610df6575f80fd5b50610692610e0536600461565d565b612dfa565b348015610e15575f80fd5b50610692610e243660046153d3565b612e22565b348015610e34575f80fd5b505f546001600160a01b031661072b565b348015610e50575f80fd5b50610692610e5f36600461531b565b612e51565b348015610e6f575f80fd5b50610795610e7e366004615680565b5f918252603a602090815260408084206038835281852054855282528084206001600160a01b0393909316845291905290205490565b348015610ebf575f80fd5b50610692610ece36600461531b565b612e5f565b348015610ede575f80fd5b50610795610eed366004615300565b6024545f908152603b602090815260408083206001600160a01b039094168352929052205490565b348015610f20575f80fd5b506106e6612e6d565b348015610f34575f80fd5b50610692610f433660046153d3565b612e7c565b610692612eab565b348015610f5b575f80fd5b50610692610f6a3660046156a3565b612ee5565b348015610f7a575f80fd5b50610692610f89366004615573565b612fb7565b348015610f99575f80fd5b50610692610fa836600461531b565b335f908152600e6020526040902055565b348015610fc4575f80fd5b50610692610fd3366004615300565b612fd3565b348015610fe3575f80fd5b50610795610ff236600461531b565b600d6020525f908152604090205481565b34801561100e575f80fd5b506013545f908152601b6020526040902054610795565b348015611030575f80fd5b5061079561103f36600461531b565b60386020525f908152604090205481565b34801561105b575f80fd5b5061069261106a366004615573565b612fe4565b34801561107a575f80fd5b506106926110893660046156cf565b613000565b348015611099575f80fd5b506106926110a836600461543b565b6130ea565b3480156110b8575f80fd5b506106636110c736600461531b565b60356020525f908152604090205460ff1681565b3480156110e6575f80fd5b506106926110f5366004615619565b613104565b348015611105575f80fd5b5061069261111436600461531b565b613119565b348015611124575f80fd5b5061069261113336600461543b565b613127565b348015611143575f80fd5b506106e661115236600461531b565b613141565b348015611162575f80fd5b50610663611171366004615749565b613274565b348015611181575f80fd5b50610795601f5481565b348015611196575f80fd5b5061079560235481565b3480156111ab575f80fd5b506106926111ba36600461531b565b6133a3565b3480156111ca575f80fd5b506106926111d9366004615619565b6133b1565b3480156111e9575f80fd5b5061079560245481565b610692611201366004615787565b6133c6565b348015611211575f80fd5b5061069261122036600461531b565b61363f565b348015611230575f80fd5b5061069261123f36600461565d565b61364d565b34801561124f575f80fd5b506106e6613675565b348015611263575f80fd5b506106636112723660046157d0565b61367f565b348015611282575f80fd5b50610795601e5481565b348015611297575f80fd5b506106636112a636600461531b565b60366020525f908152604090205460ff1681565b3480156112c5575f80fd5b506106636112d43660046157fc565b6136c9565b3480156112e4575f80fd5b506106926112f3366004615300565b613800565b348015611303575f80fd5b506016546106639060ff1681565b34801561131c575f80fd5b5061069261132b366004615680565b613876565b34801561133b575f80fd5b5061069261134a36600461543b565b6138c7565b34801561135a575f80fd5b50610692611369366004615300565b6138e1565b60606113786138f3565b905090565b5f611387826138ff565b92915050565b61139633613923565b600980546001600160a01b0319166001600160a01b03831617905550565b50565b6113c033613923565b602355565b6113ce33613923565b6113d88282613990565b5050565b6060600280546113eb90615842565b80601f016020809104026020016040519081016040528092919081815260200182805461141790615842565b80156114625780601f1061143957610100808354040283529160200191611462565b820191905f5260205f20905b81548152906001019060200180831161144557829003601f168201915b5050505050905090565b5f61147682613a8d565b6114df5760405162461bcd60e51b815260206004820152602f60248201527f4552433732315073693a20617070726f76656420717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b60648201526084015b60405180910390fd5b505f908152600660205260409020546001600160a01b031690565b816daaeb6d7670e522a718067333cd4e3b1580159061151b575060165460ff165b156115c257604051633185c44d60e21b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015611576573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061159a919061587a565b6115c257604051633b79c77360e21b81526001600160a01b03821660048201526024016114d6565b6115cc8383613ac1565b505050565b6115da33613923565b602580546001600160a01b0319166001600160a01b0392909216919091179055565b5f600161160860055490565b61137891906158a9565b61161b33613923565b600f55565b5f611629613ad5565b611608613b35565b61163a33613923565b602880546001600160a01b0319166001600160a01b039390931692909217909155602e55565b61166933613923565b602a80546001600160a01b0319166001600160a01b039390931692909217909155603055565b826daaeb6d7670e522a718067333cd4e3b158015906116b0575060165460ff165b1561176557336001600160a01b038216036116d5576116d0848484613b45565b611770565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015611722573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611746919061587a565b61176557604051633b79c77360e21b81523360048201526024016114d6565b611770848484613b45565b50505050565b61177f33613923565b6113b4816013545f90815260116020526040902055565b603480546117a390615842565b80601f01602080910402602001604051908101604052809291908181526020018280546117cf90615842565b801561181a5780601f106117f15761010080835404028352916020019161181a565b820191905f5260205f20905b8154815290600101906020018083116117fd57829003601f168201915b505050505081565b61182a613b76565b6113b481613bcf565b61183c33613923565b602780546001600160a01b0319166001600160a01b039390931692909217909155602d55565b5f8281526015602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925282916118d65750604080518082019091526014546001600160a01b0381168252600160a01b90046001600160601b031660208201525b60208101515f90612710906118f4906001600160601b0316876158bc565b6118fe91906158d3565b915196919550909350505050565b61191533613923565b5f9182526011602052604090912055565b61192e613c55565b5f8381526036602052604090205460ff1661198b5760405162461bcd60e51b815260206004820152601760248201527f616c6c6f776c6973744d696e742069732050617573656400000000000000000060448201526064016114d6565b611996338483613274565b6119dd5760405162461bcd60e51b8152602060048201526018602482015277596f7520617265206e6f742077686974656c69737465642160401b60448201526064016114d6565b81601d541015611a425760405162461bcd60e51b815260206004820152602a60248201527f616c6c6f776c6973744d696e743a204f766572206d6178206d696e747320706560448201526972206f6e652074696d6560b01b60648201526084016114d6565b5f838152601b6020526040902054821115611ab05760405162461bcd60e51b815260206004820152602860248201527f616c6c6f776c6973744d696e743a204f766572206d6178206d696e74732070656044820152671c881dd85b1b195d60c21b60648201526084016114d6565b5f838152603a60209081526040808320603883528184205484528252808320338452909152902054611ae39083906158f2565b5f848152601b60205260409020541015611b3f5760405162461bcd60e51b815260206004820152601e60248201527f596f752068617665206e6f2077686974656c6973744d696e74206c656674000060448201526064016114d6565b5f83815260186020526040902054611b589083906158bc565b3414611b765760405162461bcd60e51b81526004016114d690615905565b602054611b81611620565b611b8b90846158f2565b111580611b985750602054155b611bb45760405162461bcd60e51b81526004016114d69061593c565b5f838152603a6020908152604080832060388352818420548452825280832033845290915281208054849290611beb9084906158f2565b90915550611bfb90503383613cae565b6115cc6001601055565b611c0d613c55565b60375460ff16611c565760405162461bcd60e51b81526020600482015260146024820152731c1d589b1a58d35a5b9d081a5cc814185d5cd95960621b60448201526064016114d6565b80601e541015611cb85760405162461bcd60e51b815260206004820152602760248201527f7075626c69634d696e743a204f766572206d6178206d696e747320706572206f6044820152666e652074696d6560c81b60648201526084016114d6565b80601c541015611d185760405162461bcd60e51b815260206004820152602560248201527f7075626c69634d696e743a204f766572206d6178206d696e7473207065722077604482015264185b1b195d60da1b60648201526084016114d6565b6024545f908152603b60209081526040808320338452909152902054611d3f9082906158f2565b601c541015611d905760405162461bcd60e51b815260206004820152601b60248201527f596f752068617665206e6f207075626c69634d696e74206c656674000000000060448201526064016114d6565b80601954611d9e91906158bc565b3414611dbc5760405162461bcd60e51b81526004016114d690615905565b602054611dc7611620565b611dd190836158f2565b111580611dde5750602054155b611dfa5760405162461bcd60e51b81526004016114d69061593c565b6024545f908152603b6020908152604080832033845290915281208054839290611e259084906158f2565b90915550611e3590503382613cae565b6113b46001601055565b611e4833613923565b602455565b611e5633613923565b611e5e613c55565b6026546001600160a01b031615801590611e795750602c5415155b80611e8d57506026546001600160a01b0316155b611ef05760405162461bcd60e51b815260206004820152602e60248201527f706c656173652073657420776974686472617720416464726573735f6161206160448201526d3732103832b931b2b73a30b3b29760911b60648201526084016114d6565b6027546001600160a01b031615801590611f0b5750602d5415155b80611f1f57506027546001600160a01b0316155b611f825760405162461bcd60e51b815260206004820152602e60248201527f706c656173652073657420776974686472617720416464726573735f6262206160448201526d3732103832b931b2b73a30b3b29760911b60648201526084016114d6565b6028546001600160a01b031615801590611f9d5750602e5415155b80611fb157506028546001600160a01b0316155b6120145760405162461bcd60e51b815260206004820152602e60248201527f706c656173652073657420776974686472617720416464726573735f6363206160448201526d3732103832b931b2b73a30b3b29760911b60648201526084016114d6565b6029546001600160a01b03161580159061202f5750602f5415155b8061204357506029546001600160a01b0316155b6120a65760405162461bcd60e51b815260206004820152602e60248201527f706c656173652073657420776974686472617720416464726573735f6464206160448201526d3732103832b931b2b73a30b3b29760911b60648201526084016114d6565b602a546001600160a01b0316158015906120c1575060305415155b806120d55750602a546001600160a01b0316155b6121385760405162461bcd60e51b815260206004820152602e60248201527f706c656173652073657420776974686472617720416464726573735f6565206160448201526d3732103832b931b2b73a30b3b29760911b60648201526084016114d6565b602b546001600160a01b031615801590612153575060315415155b806121675750602b546001600160a01b0316155b6121ca5760405162461bcd60e51b815260206004820152602e60248201527f706c656173652073657420776974686472617720416464726573735f6666206160448201526d3732103832b931b2b73a30b3b29760911b60648201526084016114d6565b60265447905f906001600160a01b03161561229a57602654602c546001600160a01b0390911690612710906121ff90856158bc565b61220991906158d3565b6040515f81818185875af1925050503d805f8114612242576040519150601f19603f3d011682016040523d82523d5f602084013e612247565b606091505b5050809150508061229a5760405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2077697468647261775f6161204574686572000000000060448201526064016114d6565b6027546001600160a01b03161561236657602754602d546001600160a01b0390911690612710906122cb90856158bc565b6122d591906158d3565b6040515f81818185875af1925050503d805f811461230e576040519150601f19603f3d011682016040523d82523d5f602084013e612313565b606091505b505080915050806123665760405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2077697468647261775f6262204574686572000000000060448201526064016114d6565b6028546001600160a01b03161561243257602854602e546001600160a01b03909116906127109061239790856158bc565b6123a191906158d3565b6040515f81818185875af1925050503d805f81146123da576040519150601f19603f3d011682016040523d82523d5f602084013e6123df565b606091505b505080915050806124325760405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2077697468647261775f6363204574686572000000000060448201526064016114d6565b6029546001600160a01b0316156124fe57602954602f546001600160a01b03909116906127109061246390856158bc565b61246d91906158d3565b6040515f81818185875af1925050503d805f81146124a6576040519150601f19603f3d011682016040523d82523d5f602084013e6124ab565b606091505b505080915050806124fe5760405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2077697468647261775f6464204574686572000000000060448201526064016114d6565b602a546001600160a01b0316156125ca57602a546030546001600160a01b03909116906127109061252f90856158bc565b61253991906158d3565b6040515f81818185875af1925050503d805f8114612572576040519150601f19603f3d011682016040523d82523d5f602084013e612577565b606091505b505080915050806125ca5760405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2077697468647261775f6565204574686572000000000060448201526064016114d6565b602b546001600160a01b03161561269657602b546031546001600160a01b0390911690612710906125fb90856158bc565b61260591906158d3565b6040515f81818185875af1925050503d805f811461263e576040519150601f19603f3d011682016040523d82523d5f602084013e612643565b606091505b505080915050806126965760405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2077697468647261775f6666204574686572000000000060448201526064016114d6565b6025544792506001600160a01b031615612704576025546040516001600160a01b039091169083905f81818185875af1925050503d805f81146126f4576040519150601f19603f3d011682016040523d82523d5f602084013e6126f9565b606091505b505080915050612761565b5f546001600160a01b03166001600160a01b0316826040515f6040518083038185875af1925050503d805f8114612756576040519150601f19603f3d011682016040523d82523d5f602084013e61275b565b606091505b50909150505b806127ae5760405162461bcd60e51b815260206004820152601860248201527f4661696c656420746f207769746864726177204574686572000000000000000060448201526064016114d6565b50506127ba6001601055565b565b826daaeb6d7670e522a718067333cd4e3b158015906127dd575060165460ff165b1561288d57336001600160a01b038216036127fd576116d0848484613cc7565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa15801561284a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061286e919061587a565b61288d57604051633b79c77360e21b81523360048201526024016114d6565b611770848484613cc7565b336128a282612b04565b6001600160a01b0316146128eb5760405162461bcd60e51b815260206004820152601060248201526f34b9b73a1037bbb732b9103a37b5b2b760811b60448201526064016114d6565b603754610100900460ff161561292f5760405162461bcd60e51b81526020600482015260096024820152686e6f7420616c6c6f7760b81b60448201526064016114d6565b6113b481613ce1565b61294133613923565b603780549115156101000261ff0019909216919091179055565b60605f61296783612b3f565b90505f816001600160401b038111156129825761298261545b565b6040519080825280602002602001820160405280156129ab578160200160208202803683370190505b5090505f60015b60016129bd60055490565b6129c791906158a9565b811015612a81576040516320c2ce9960e21b815260048101829052309063830b3a6490602401602060405180830381865afa158015612a08573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a2c9190615962565b6001600160a01b0316866001600160a01b031603612a6f57808383612a508161597d565b945081518110612a6257612a62615995565b6020026020010181815250505b80612a798161597d565b9150506129b2565b5090949350505050565b612a9433613923565b60336113d882826159ee565b612aa933613923565b602980546001600160a01b0319166001600160a01b039390931692909217909155602f55565b612ad833613923565b5f8281526038602052604081208290556023805460019290612afb9084906158f2565b90915550505050565b5f80612b0f83613d3c565b509392505050565b612b2033613923565b601f55565b612b2e33613923565b5f9182526012602052604090912055565b5f6001600160a01b038216612bac5760405162461bcd60e51b815260206004820152602d60248201527f4552433732315073693a2062616c616e636520717565727920666f722074686560448201526c207a65726f206164647265737360981b60648201526084016114d6565b5f60015b600554811015612c0557612bc381613a8d565b15612bf557612bd181612b04565b6001600160a01b0316846001600160a01b031603612bf557612bf28261597d565b91505b612bfe8161597d565b9050612bb0565b5092915050565b612c14613b76565b6127ba5f613dd1565b612c2633613923565b6113b481613e20565b81612c3981612b04565b6001600160a01b0316336001600160a01b031614612cac5760405162461bcd60e51b815260206004820152602a60248201527f5265737472696374417070726f76653a206f7065726174696f6e206973206f6e604482015269363c903437b63232b91760b11b60648201526084016114d6565b505f918252600d602052604090912055565b612cc733613923565b601c55565b6040516331a9108f60e11b8152600481018290525f903090636352211e90602401602060405180830381865afa925050508015612d26575060408051601f3d908101601f19168201909252612d2391810190615962565b60015b61138757505f919050565b919050565b60605f80612d4384612b3f565b90505f816001600160401b03811115612d5e57612d5e61545b565b604051908082528060200260200182016040528015612d87578160200160208202803683370190505b50905060015b828414612df157612d9d81613a8d565b15612de957856001600160a01b0316612db582612b04565b6001600160a01b031603612de95780828580600101965081518110612ddc57612ddc615995565b6020026020010181815250505b600101612d8d565b50949350505050565b612e0333613923565b5f91825260366020526040909120805460ff1916911515919091179055565b612e2b33613923565b602680546001600160a01b0319166001600160a01b039390931692909217909155602c55565b612e5a33613923565b601a55565b612e6833613923565b602055565b6060600380546113eb90615842565b612e8533613923565b602b80546001600160a01b0319166001600160a01b039390931692909217909155603155565b612eb433613923565b612ebc613c55565b5f3411612edb5760405162461bcd60e51b81526004016114d690615905565b6127ba6001601055565b816daaeb6d7670e522a718067333cd4e3b15801590612f06575060165460ff165b15612fad57604051633185c44d60e21b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015612f61573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f85919061587a565b612fad57604051633b79c77360e21b81526001600160a01b03821660048201526024016114d6565b6115cc8383613e64565b612fc033613923565b6037805460ff1916911515919091179055565b612fdb613b76565b6113b481613ee2565b612fed33613923565b6016805460ff1916911515919091179055565b836daaeb6d7670e522a718067333cd4e3b15801590613021575060165460ff165b156130d757336001600160a01b038216036130475761304285858585613f0b565b6130e3565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015613094573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130b8919061587a565b6130d757604051633b79c77360e21b81523360048201526024016114d6565b6130e385858585613f0b565b5050505050565b6130f333613923565b5f918252601b602052604090912055565b61310d33613923565b60326113d882826159ee565b61312233613923565b602155565b61313033613923565b5f9182526018602052604090912055565b606061314c82613a8d565b6131985760405162461bcd60e51b815260206004820152601f60248201527f55524920717565727920666f72206e6f6e6578697374656e7420746f6b656e0060448201526064016114d6565b6131a482602154101590565b156131e4576131b1613f3d565b6131ba83613f4c565b60346040516020016131ce93929190615aa9565b6040516020818303038152906040529050919050565b603280546131f190615842565b80601f016020809104026020016040519081016040528092919081815260200182805461321d90615842565b80156132685780601f1061323f57610100808354040283529160200191613268565b820191905f5260205f20905b81548152906001019060200180831161324b57829003601f168201915b50505050509050919050565b6040516bffffffffffffffffffffffff19606085901b1660208201525f9081906034016040516020818303038152906040528051906020012090505f5b835181101561338a578381815181106132cc576132cc615995565b6020026020010151821061332a578381815181106132ec576132ec615995565b60200260200101518260405160200161330f929190918252602082015260400190565b60405160208183030381529060405280519060200120613376565b8184828151811061333d5761333d615995565b602002602001015160405160200161335f929190918252602082015260400190565b604051602081830303815290604052805190602001205b9150806133828161597d565b9150506132b1565b505f848152601260205260409020541490509392505050565b6133ac33613923565b601955565b6133ba33613923565b60346113d882826159ee565b6133ce613c55565b5f8481526035602052604090205460ff1661342b5760405162461bcd60e51b815260206004820152601760248201527f77686974656c6973744d696e742069732050617573656400000000000000000060448201526064016114d6565b613437338584846136c9565b61347e5760405162461bcd60e51b8152602060048201526018602482015277596f7520617265206e6f742077686974656c69737465642160401b60448201526064016114d6565b5f82116134bf5760405162461bcd60e51b815260206004820152600f60248201526e596f752068617665206e6f20574c2160881b60448201526064016114d6565b828210156135205760405162461bcd60e51b815260206004820152602860248201527f77686974656c6973744d696e743a204f766572206d6178206d696e74732070656044820152671c881dd85b1b195d60c21b60648201526084016114d6565b5f8481526039602090815260408083203384529091529020546135449084906158f2565b8210156135935760405162461bcd60e51b815260206004820152601e60248201527f596f752068617665206e6f2077686974656c6973744d696e74206c656674000060448201526064016114d6565b82601a546135a191906158bc565b34146135bf5760405162461bcd60e51b81526004016114d690615905565b6020546135ca611620565b6135d490856158f2565b1115806135e15750602054155b6135fd5760405162461bcd60e51b81526004016114d69061593c565b5f848152603960209081526040808320338452909152812080548592906136259084906158f2565b9091555061363590503384613cae565b6117706001601055565b61364833613923565b602255565b61365633613923565b5f91825260356020526040909120805460ff1916911515919091179055565b6060611378613fdb565b5f61368a838361405a565b15155f0361369957505f611387565b6001600160a01b038084165f9081526007602090815260408083209386168352929052205460ff165b9392505050565b6040516bffffffffffffffffffffffff19606086901b166020820152603481018390525f9081906054016040516020818303038152906040528051906020012090505f5b83518110156137e65783818151811061372857613728615995565b602002602001015182106137865783818151811061374857613748615995565b60200260200101518260405160200161376b929190918252602082015260400190565b604051602081830303815290604052805190602001206137d2565b8184828151811061379957613799615995565b60200260200101516040516020016137bb929190918252602082015260400190565b604051602081830303815290604052805190602001205b9150806137de8161597d565b91505061370d565b505f85815260116020526040902054149050949350505050565b613808613b76565b6001600160a01b03811661386d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016114d6565b6113b481613dd1565b61387f33613923565b601f5461388a611620565b61389490846158f2565b1115806138a15750601f54155b6138bd5760405162461bcd60e51b81526004016114d69061593c565b6113d88183613cae565b6138d033613923565b5f9182526038602052604090912055565b6138ea33613923565b6113b481614079565b6060611378600a6140bd565b5f6001600160e01b0319821663152a902d60e11b14806113875750611387826140c9565b6001600160a01b0381165f9081526017602052604090205460ff16613953335b6001600160a01b031660146140ed565b6040516020016139639190615b44565b604051602081830303815290604052906113d85760405162461bcd60e51b81526004016114d691906153c1565b6127106001600160601b03821611156139fe5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b60648201526084016114d6565b6001600160a01b038216613a545760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c69642072656365697665720000000000000060448201526064016114d6565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217601455565b600881811c5f9081526020919091526040812054600160ff1b60ff84161c1615613ab857505f919050565b61138782614282565b613acb828261429d565b6113d88282614318565b6005545f9081908190613aec9060081c60016158f2565b9050815b81811015613b2f575f81815260086020526040902054613b0f81614429565b613b1990866158f2565b9450508080613b279061597d565b915050613af0565b50505090565b5f600160055461137891906158a9565b613b4f3382614441565b613b6b5760405162461bcd60e51b81526004016114d690615b90565b6115cc838383614504565b5f546001600160a01b031633146127ba5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016114d6565b6001600160a01b0381165f9081526017602052604090205460ff1615613bf433613943565b604051602001613c049190615be4565b60405160208183030381529060405290613c315760405162461bcd60e51b81526004016114d691906153c1565b506001600160a01b03165f908152601760205260409020805460ff19166001179055565b600260105403613ca75760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016114d6565b6002601055565b6113d8828260405180602001604052805f8152506146f8565b6115cc83838360405180602001604052805f815250613000565b5f613ceb82612b04565b9050613cf8600883614737565b60405182905f906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a46113d8815f846001614762565b5f80613d4783613a8d565b613da85760405162461bcd60e51b815260206004820152602c60248201527f4552433732315073693a206f776e657220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084016114d6565b613db183614784565b5f818152600460205260409020546001600160a01b031694909350915050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b613e2b600a82614790565b506040516001600160a01b0382169033907f3b01c97343869ca2757fcc37cdb8f71683b0a7aed858e3755f4529a1db857292905f90a350565b613e6d826147a4565b80613e76575080155b613ed85760405162461bcd60e51b815260206004820152602d60248201527f5265737472696374417070726f76653a2043616e206e6f7420617070726f766560448201526c103637b1b5b2b2103a37b5b2b760991b60648201526084016114d6565b6113d882826147af565b613eeb81613923565b6001600160a01b03165f908152601760205260409020805460ff19169055565b613f153383614441565b613f315760405162461bcd60e51b81526004016114d690615b90565b61177084848484614872565b6060603380546113eb90615842565b60605f613f588361488b565b60010190505f816001600160401b03811115613f7657613f7661545b565b6040519080825280601f01601f191660200182016040528015613fa0576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084613faa57509392505050565b60605f80613feb81612710611862565b91509150614034613ffb82613f4c565b61400f846001600160a01b031660146140ed565b604051602001614020929190615c3a565b604051602081830303815290604052614962565b6040516020016140449190615cbf565b6040516020818303038152906040529250505090565b5f8061406584614ac0565b90506140718382614b00565b949350505050565b614084600a82614b96565b506040516001600160a01b0382169033907fbd0af1fe0a2c1c7bb340c17a284a291138979c8eeb797e176dbd1c415199af3c905f90a350565b60605f6136c283614baa565b5f6001600160e01b03198216630101c11560e71b1480611387575061138782614c02565b60605f6140fb8360026158bc565b6141069060026158f2565b6001600160401b0381111561411d5761411d61545b565b6040519080825280601f01601f191660200182016040528015614147576020820181803683370190505b509050600360fc1b815f8151811061416157614161615995565b60200101906001600160f81b03191690815f1a905350600f60fb1b8160018151811061418f5761418f615995565b60200101906001600160f81b03191690815f1a9053505f6141b18460026158bc565b6141bc9060016158f2565b90505b6001811115614233576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106141f0576141f0615995565b1a60f81b82828151811061420657614206615995565b60200101906001600160f81b03191690815f1a90535060049490941c9361422c81615d03565b90506141bf565b5083156136c25760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016114d6565b5f61428c60055490565b821080156113875750506001111590565b6001600160a01b038216156113d8576142b68183614c51565b6113d85760405162461bcd60e51b815260206004820152602d60248201527f5265737472696374417070726f76653a2054686520636f6e747261637420697360448201526c103737ba1030b63637bbb2b21760991b60648201526084016114d6565b5f61432282612b04565b9050806001600160a01b0316836001600160a01b0316036143915760405162461bcd60e51b8152602060048201526024808201527f4552433732315073693a20617070726f76616c20746f2063757272656e74206f6044820152633bb732b960e11b60648201526084016114d6565b336001600160a01b03821614806143ad57506143ad813361367f565b61441f5760405162461bcd60e51b815260206004820152603b60248201527f4552433732315073693a20617070726f76652063616c6c6572206973206e6f7460448201527f206f776e6572206e6f7220617070726f76656420666f7220616c6c000000000060648201526084016114d6565b6115cc8383614c5d565b5f5b8115612d31575f1982019091169060010161442b565b5f61444b82613a8d565b6144af5760405162461bcd60e51b815260206004820152602f60248201527f4552433732315073693a206f70657261746f7220717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b60648201526084016114d6565b5f6144b983612b04565b9050806001600160a01b0316846001600160a01b031614806144f45750836001600160a01b03166144e98461146c565b6001600160a01b0316145b806140715750614071818561367f565b5f8061450f83613d3c565b91509150846001600160a01b0316826001600160a01b0316146145895760405162461bcd60e51b815260206004820152602c60248201527f4552433732315073693a207472616e73666572206f6620746f6b656e2074686160448201526b3a1034b9903737ba1037bbb760a11b60648201526084016114d6565b6001600160a01b0384166145ef5760405162461bcd60e51b815260206004820152602760248201527f4552433732315073693a207472616e7366657220746f20746865207a65726f206044820152666164647265737360c81b60648201526084016114d6565b6145f95f84614c5d565b5f6146058460016158f2565b600881901c5f90815260016020526040902054909150600160ff1b60ff83161c16158015614634575060055481105b1561466a575f81815260046020526040902080546001600160a01b0319166001600160a01b03881617905561466a600182614737565b5f84815260046020526040902080546001600160a01b0319166001600160a01b0387161790558184146146a2576146a2600185614737565b83856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46146f08686866001614762565b505050505050565b5f61470260055490565b905061470e8484614cca565b61471b5f85838686614e44565b6117705760405162461bcd60e51b81526004016114d690615d18565b600881901c5f90815260209290925260409091208054600160ff1b60ff9093169290921c9091179055565b6001600160a01b03841615611770575f828152600d6020526040812055611770565b5f611387600183614f77565b5f6136c2836001600160a01b03841661506b565b5f611387338361405a565b336001600160a01b038316036148075760405162461bcd60e51b815260206004820152601c60248201527f4552433732315073693a20617070726f766520746f2063616c6c65720000000060448201526064016114d6565b335f8181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61487d848484614504565b61471b848484600185614e44565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106148c95772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106148f5576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061491357662386f26fc10000830492506010015b6305f5e100831061492b576305f5e100830492506008015b612710831061493f57612710830492506004015b60648310614951576064830492506002015b600a83106113875760010192915050565b606081515f0361497f57505060408051602081019091525f815290565b5f604051806060016040528060408152602001615dd96040913990505f6003845160026149ac91906158f2565b6149b691906158d3565b6149c19060046158bc565b90505f6149cf8260206158f2565b6001600160401b038111156149e6576149e661545b565b6040519080825280601f01601f191660200182016040528015614a10576020820181803683370190505b509050818152600183018586518101602084015b81831015614a7c576003830192508251603f8160121c168501518253600182019150603f81600c1c168501518253600182019150603f8160061c168501518253600182019150603f8116850151825350600101614a24565b600389510660018114614a965760028114614aa757614ab2565b613d3d60f01b600119830152614ab2565b603d60f81b5f198301525b509398975050505050505050565b6001600160a01b0381165f908152600e602052604081205415614af857506001600160a01b03165f908152600e602052604090205490565b5050600f5490565b600c545f9060ff16614b1457506001611387565b614b1d8361514e565b806136c25750600954604051630f8350ed60e41b81526001600160a01b038581166004830152602482018590529091169063f8350ed090604401602060405180830381865afa158015614b72573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136c2919061587a565b5f6136c2836001600160a01b038416615176565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561326857602002820191905f5260205f20905b815481526020019060010190808311614be35750505050509050919050565b5f6001600160e01b031982166380ac58cd60e01b1480614c3257506001600160e01b03198216635b5e139f60e01b145b8061138757506301ffc9a760e01b6001600160e01b0319831614611387565b5f8061406533856151c2565b5f81815260066020526040902080546001600160a01b0319166001600160a01b0384169081179091558190614c9182612b04565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b5f614cd460055490565b90505f8211614d335760405162461bcd60e51b815260206004820152602560248201527f4552433732315073693a207175616e74697479206d7573742062652067726561604482015264074657220360dc1b60648201526084016114d6565b6001600160a01b038316614d955760405162461bcd60e51b815260206004820152602360248201527f4552433732315073693a206d696e7420746f20746865207a65726f206164647260448201526265737360e81b60648201526084016114d6565b8160055f828254614da691906158f2565b90915550505f81815260046020526040902080546001600160a01b0319166001600160a01b038516179055614ddc600182614737565b614de85f848385614762565b805b614df483836158f2565b8110156117705760405181906001600160a01b038616905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a480614e3c8161597d565b915050614dea565b5f6001600160a01b0385163b15614f6a57506001835b614e6484866158f2565b811015614f6457604051630a85bd0160e11b81526001600160a01b0387169063150b7a0290614e9d9033908b9086908990600401615d6d565b6020604051808303815f875af1925050508015614ed7575060408051601f3d908101601f19168201909252614ed491810190615da9565b60015b614f32573d808015614f04576040519150601f19603f3d011682016040523d82523d5f602084013e614f09565b606091505b5080515f03614f2a5760405162461bcd60e51b81526004016114d690615d18565b805181602001fd5b828015614f4f57506001600160e01b03198116630a85bd0160e11b145b92505080614f5c8161597d565b915050614e5a565b50614f6e565b5060015b95945050505050565b600881901c5f8181526020849052604081205490919060ff808516919082181c8015614fb857614fa6816151f2565b60ff168203600884901b179350615062565b5f83116150245760405162461bcd60e51b815260206004820152603460248201527f4269744d6170733a205468652073657420626974206265666f7265207468652060448201527334b73232bc103237b2b9b713ba1032bc34b9ba1760611b60648201526084016114d6565b505f199091015f81815260208690526040902054909190801561505d5761504a816151f2565b60ff0360ff16600884901b179350615062565b614fb8565b50505092915050565b5f8181526001830160205260408120548015615145575f61508d6001836158a9565b85549091505f906150a0906001906158a9565b90508181146150ff575f865f0182815481106150be576150be615995565b905f5260205f200154905080875f0184815481106150de576150de615995565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061511057615110615dc4565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050611387565b5f915050611387565b5f611387600a836001600160a01b0381165f90815260018301602052604081205415156136c2565b5f8181526001830160205260408120546151bb57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155611387565b505f611387565b5f818152600d6020526040812054156151e957505f818152600d6020526040902054611387565b6136c283614ac0565b5f6040518061012001604052806101008152602001615e19610100913960f87e818283848586878898a8b8c8d8e8f929395969799a9b9d9e9faaeb6bedeeff61523a8561525b565b02901c8151811061524d5761524d615995565b016020015160f81c92915050565b5f808211615267575f80fd5b505f8190031690565b602080825282518282018190525f9190848201906040850190845b818110156152b05783516001600160a01b03168352928401929184019160010161528b565b50909695505050505050565b6001600160e01b0319811681146113b4575f80fd5b5f602082840312156152e1575f80fd5b81356136c2816152bc565b6001600160a01b03811681146113b4575f80fd5b5f60208284031215615310575f80fd5b81356136c2816152ec565b5f6020828403121561532b575f80fd5b5035919050565b5f8060408385031215615343575f80fd5b823561534e816152ec565b915060208301356001600160601b0381168114615369575f80fd5b809150509250929050565b5f5b8381101561538e578181015183820152602001615376565b50505f910152565b5f81518084526153ad816020860160208601615374565b601f01601f19169290920160200192915050565b602081525f6136c26020830184615396565b5f80604083850312156153e4575f80fd5b82356153ef816152ec565b946020939093013593505050565b5f805f6060848603121561540f575f80fd5b833561541a816152ec565b9250602084013561542a816152ec565b929592945050506040919091013590565b5f806040838503121561544c575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156154975761549761545b565b604052919050565b5f82601f8301126154ae575f80fd5b813560206001600160401b038211156154c9576154c961545b565b8160051b6154d882820161546f565b92835284810182019282810190878511156154f1575f80fd5b83870192505b84831015615510578235825291830191908301906154f7565b979650505050505050565b5f805f6060848603121561552d575f80fd5b833592506020840135915060408401356001600160401b03811115615550575f80fd5b61555c8682870161549f565b9150509250925092565b80151581146113b4575f80fd5b5f60208284031215615583575f80fd5b81356136c281615566565b602080825282518282018190525f9190848201906040850190845b818110156152b0578351835292840192918401916001016155a9565b5f6001600160401b038311156155dd576155dd61545b565b6155f0601f8401601f191660200161546f565b9050828152838383011115615603575f80fd5b828260208301375f602084830101529392505050565b5f60208284031215615629575f80fd5b81356001600160401b0381111561563e575f80fd5b8201601f8101841361564e575f80fd5b614071848235602084016155c5565b5f806040838503121561566e575f80fd5b82359150602083013561536981615566565b5f8060408385031215615691575f80fd5b823591506020830135615369816152ec565b5f80604083850312156156b4575f80fd5b82356156bf816152ec565b9150602083013561536981615566565b5f805f80608085870312156156e2575f80fd5b84356156ed816152ec565b935060208501356156fd816152ec565b92506040850135915060608501356001600160401b0381111561571e575f80fd5b8501601f8101871361572e575f80fd5b61573d878235602084016155c5565b91505092959194509250565b5f805f6060848603121561575b575f80fd5b8335615766816152ec565b92506020840135915060408401356001600160401b03811115615550575f80fd5b5f805f806080858703121561579a575f80fd5b84359350602085013592506040850135915060608501356001600160401b038111156157c4575f80fd5b61573d8782880161549f565b5f80604083850312156157e1575f80fd5b82356157ec816152ec565b91506020830135615369816152ec565b5f805f806080858703121561580f575f80fd5b843561581a816152ec565b9350602085013592506040850135915060608501356001600160401b038111156157c4575f80fd5b600181811c9082168061585657607f821691505b60208210810361587457634e487b7160e01b5f52602260045260245ffd5b50919050565b5f6020828403121561588a575f80fd5b81516136c281615566565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561138757611387615895565b808202811582820484141761138757611387615895565b5f826158ed57634e487b7160e01b5f52601260045260245ffd5b500490565b8082018082111561138757611387615895565b60208082526018908201527f4554482076616c7565206973206e6f7420636f72726563740000000000000000604082015260600190565b6020808252600c908201526b4e6f206d6f7265204e46547360a01b604082015260600190565b5f60208284031215615972575f80fd5b81516136c2816152ec565b5f6001820161598e5761598e615895565b5060010190565b634e487b7160e01b5f52603260045260245ffd5b601f8211156115cc575f81815260208120601f850160051c810160208610156159cf5750805b601f850160051c820191505b818110156146f0578281556001016159db565b81516001600160401b03811115615a0757615a0761545b565b615a1b81615a158454615842565b846159a9565b602080601f831160018114615a4e575f8415615a375750858301515b5f19600386901b1c1916600185901b1785556146f0565b5f85815260208120601f198616915b82811015615a7c57888601518255948401946001909101908401615a5d565b5085821015615a9957878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f84516020615abb8285838a01615374565b855191840191615ace8184848a01615374565b85549201915f90615ade81615842565b60018281168015615af65760018114615b0b57615b34565b60ff1984168752821515830287019450615b34565b895f52855f205f5b84811015615b2c57815489820152908301908701615b13565b505082870194505b50929a9950505050505050505050565b67030b1b1b7bab73a160c51b81525f8251615b66816008850160208701615374565b721034b9903737ba1030b71037b832b930ba37b960691b6008939091019283015250601b01919050565b60208082526034908201527f4552433732315073693a207472616e736665722063616c6c6572206973206e6f6040820152731d081bdddb995c881b9bdc88185c1c1c9bdd995960621b606082015260800190565b67030b1b1b7bab73a160c51b81525f8251615c06816008850160208701615374565b7f20697320616c72656164792068617320616e206f70657261746f7220726f6c656008939091019283015250602801919050565b7f7b2273656c6c65725f6665655f62617369735f706f696e7473223a000000000081525f8351615c7181601b850160208801615374565b721610113332b2afb932b1b4b834b2b73a111d1160691b601b918401918201528351615ca481602e840160208801615374565b61227d60f01b602e9290910191820152603001949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081525f8251615cf681601d850160208701615374565b91909101601d0192915050565b5f81615d1157615d11615895565b505f190190565b60208082526035908201527f4552433732315073693a207472616e7366657220746f206e6f6e20455243373260408201527418a932b1b2b4bb32b91034b6b83632b6b2b73a32b960591b606082015260800190565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f90615d9f90830184615396565b9695505050505050565b5f60208284031215615db9575f80fd5b81516136c2816152bc565b634e487b7160e01b5f52603160045260245ffdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f0001020903110a19042112290b311a3905412245134d2a550c5d32651b6d3a7506264262237d468514804e8d2b95569d0d495ea533a966b11c886eb93bc176c9071727374353637324837e9b47af86c7155181ad4fd18ed32c9096db57d59ee30e2e4a6a5f92a6be3498aae067ddb2eb1d5989b56fd7baf33ca0c2ee77e5caf7ff0810182028303840444c545c646c7425617c847f8c949c48a4a8b087b8c0c816365272829aaec650acd0d28fdad4e22d6991bd97dfdcea58b4d6f29fede4f6fe0f1f2f3f4b5b6b607b8b93a3a7b7bf357199c5abcfd9e168bcdee9b3f1ecf5fd1e3e5a7a8aa2b670c4ced8bbe8f0f4fc3d79a1c3cde7effb78cce6facbf9f8a2646970667358221220df1a468af855e4daf5b4dd55626c27bcd477128fac9099d0973f297784be571364736f6c63430008150033

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

00000000000000000000000027d2210a381e7d5921fbb4df6fa39fd875cecb5700000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000005dc

-----Decoded View---------------
Arg [0] : _royaltyReceiver (address): 0x27d2210a381e7D5921Fbb4dF6Fa39fd875ceCB57
Arg [1] : _royaltyFraction (uint96): 750
Arg [2] : _aaPercAdd (uint256): 1500

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000027d2210a381e7d5921fbb4df6fa39fd875cecb57
Arg [1] : 00000000000000000000000000000000000000000000000000000000000002ee
Arg [2] : 00000000000000000000000000000000000000000000000000000000000005dc


Deployed Bytecode Sourcemap

140969:19552:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;159761:181;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;144257:179;;;;;;;;;;-1:-1:-1;144257:179:0;;;;;:::i;:::-;;:::i;:::-;;;1228:14:1;;1221:22;1203:41;;1191:2;1176:18;144257:179:0;1063:187:1;160058:105:0;;;;;;;;;;-1:-1:-1;160058:105:0;;;;;:::i;:::-;;:::i;:::-;;146027:111;;;;;;;;;;-1:-1:-1;146027:111:0;;;;;:::i;:::-;;:::i;144079:157::-;;;;;;;;;;-1:-1:-1;144079:157:0;;;;;:::i;:::-;;:::i;100146:100::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;134863:33::-;;;;;;;;;;-1:-1:-1;134863:33:0;;;;;;;;101701:311;;;;;;;;;;-1:-1:-1;101701:311:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;3188:32:1;;;3170:51;;3158:2;3143:18;101701:311:0;3024:203:1;158408:157:0;;;;;;;;;;-1:-1:-1;158408:157:0;;;;;:::i;:::-;;:::i;157758:106::-;;;;;;;;;;-1:-1:-1;157758:106:0;;;;;:::i;:::-;;:::i;149059:103::-;;;;;;;;;;;;;:::i;:::-;;;3698:25:1;;;3686:2;3671:18;149059:103:0;3552:177:1;159950:100:0;;;;;;;;;;-1:-1:-1;159950:100:0;;;;;:::i;:::-;;:::i;115276:122::-;;;;;;;;;;;;;:::i;156851:130::-;;;;;;;;;;-1:-1:-1;156851:130:0;;;;;:::i;:::-;;:::i;141303:32::-;;;;;;;;;;;;;;;;141250:48;;;;;;;;;;-1:-1:-1;141250:48:0;;;;;:::i;:::-;;;;;;;;;;;;;;147097:148;;;;;;;;;;-1:-1:-1;147097:148:0;;;;;:::i;:::-;147196:10;;147164:7;147186:21;;;:9;:21;;;;;;;;147208:8;:20;;;;;;147186:43;;;;;;;-1:-1:-1;;;;;147186:53:0;;;;;;;;;;;147097:148;157309:130;;;;;;;;;;-1:-1:-1;157309:130:0;;;;;:::i;:::-;;:::i;135001:49::-;;;;;;;;;;-1:-1:-1;135001:49:0;;;;;:::i;:::-;;;;;;;;;;;;;;158573:163;;;;;;;;;;-1:-1:-1;158573:163:0;;;;;:::i;:::-;;:::i;148447:118::-;;;;;;;;;;-1:-1:-1;148447:118:0;;;;;:::i;:::-;;:::i;142034:38::-;;;;;;;;;;;;;:::i;160221:115::-;;;;;;;;;;-1:-1:-1;160221:115:0;;;;;:::i;:::-;;:::i;156622:130::-;;;;;;;;;;-1:-1:-1;156622:130:0;;;;;:::i;:::-;;:::i;93060:442::-;;;;;;;;;;-1:-1:-1;93060:442:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;4825:32:1;;;4807:51;;4889:2;4874:18;;4867:34;;;;4780:18;93060:442:0;4633:274:1;148571:156:0;;;;;;;;;;-1:-1:-1;148571:156:0;;;;;:::i;:::-;;:::i;141122:46::-;;;;;;;;;;-1:-1:-1;141122:46:0;;;;;:::i;:::-;;;;;;;;;;;;;;141217:26;;;;;;;;;;;;;;;;151049:852;;;;;;:::i;:::-;;:::i;151925:667::-;;;;;;:::i;:::-;;:::i;141340:35::-;;;;;;;;;;;;;;;;146142:111;;;;;;;;;;-1:-1:-1;146142:111:0;;;;;:::i;:::-;;:::i;134417:34::-;;;;;;;;;;-1:-1:-1;134417:34:0;;;;-1:-1:-1;;;;;134417:34:0;;;152828:2260;;;:::i;142194:31::-;;;;;;;;;;-1:-1:-1;142194:31:0;;;;;;;;145475:110;;;;;;;;;;-1:-1:-1;145475:110:0;;;;;:::i;:::-;145542:7;145564:15;;;:8;:15;;;;;;;145475:110;129518:143;;;;;;;;;;;;129618:42;129518:143;;141173:39;;;;;;;;;;;;;;;;158744:171;;;;;;;;;;-1:-1:-1;158744:171:0;;;;;:::i;:::-;;:::i;155108:201::-;;;;;;;;;;-1:-1:-1;155108:201:0;;;;;:::i;:::-;;:::i;155338:98::-;;;;;;;;;;-1:-1:-1;155338:98:0;;;;;:::i;:::-;;:::i;155477:481::-;;;;;;;;;;-1:-1:-1;155477:481:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;141448:23::-;;;;;;;;;;;;;;;;135081:27;;;;;;;;;;;;;;;;141476:23;;;;;;;;;;;;;;;;149222:103;;;;;;;;;;-1:-1:-1;149222:103:0;;;;;:::i;:::-;;:::i;157080:130::-;;;;;;;;;;-1:-1:-1;157080:130:0;;;;;:::i;:::-;;:::i;123906:22::-;;;;;;;;;;;;;;;;145756:152;;;;;;;;;;-1:-1:-1;145756:152:0;;;;;:::i;:::-;;:::i;99543:222::-;;;;;;;;;;-1:-1:-1;99543:222:0;;;;;:::i;:::-;;:::i;125600:113::-;;;;;;;;;;-1:-1:-1;125600:113:0;;;;;:::i;:::-;-1:-1:-1;;;;;125684:21:0;125660:4;125684:21;;;:10;:21;;;;;;;;;125600:113;145206:107;;;;;;;;;;-1:-1:-1;145206:107:0;;;;;:::i;:::-;;:::i;148733:156::-;;;;;;;;;;-1:-1:-1;148733:156:0;;;;;:::i;:::-;;:::i;98991:490::-;;;;;;;;;;-1:-1:-1;98991:490:0;;;;;:::i;:::-;;:::i;117947:103::-;;;;;;;;;;;;;:::i;159572:181::-;;;;;;;;;;-1:-1:-1;159572:181:0;;;;;:::i;:::-;;:::i;146967:126::-;;;;;;;;;;-1:-1:-1;146967:126:0;;;;;:::i;:::-;147066:10;;147034:7;147056:21;;;:9;:21;;;;;;;;-1:-1:-1;;;;;147056:31:0;;;;;;;;;;;146967:126;137889:176;;;;;;;;;;-1:-1:-1;137889:176:0;;;;;:::i;:::-;;:::i;147867:100::-;;;;;;;;;;-1:-1:-1;147867:100:0;;;;;:::i;:::-;;:::i;156025:267::-;;;;;;;;;;-1:-1:-1;156025:267:0;;;;;:::i;:::-;;:::i;141504:25::-;;;;;;;;;;;;;;;;111684:601;;;;;;;;;;-1:-1:-1;111684:601:0;;;;;:::i;:::-;;:::i;148176:131::-;;;;;;;;;;-1:-1:-1;148176:131:0;;;;;:::i;:::-;;:::i;156393:130::-;;;;;;;;;;-1:-1:-1;156393:130:0;;;;;:::i;:::-;;:::i;117299:87::-;;;;;;;;;;-1:-1:-1;117345:7:0;117372:6;-1:-1:-1;;;;;117372:6:0;117299:87;;146289:103;;;;;;;;;;-1:-1:-1;146289:103:0;;;;;:::i;:::-;;:::i;147249:172::-;;;;;;;;;;-1:-1:-1;147249:172:0;;;;;:::i;:::-;147338:7;147360:22;;;:9;:22;;;;;;;;147383:8;:21;;;;;;147360:45;;;;;;;-1:-1:-1;;;;;147360:55:0;;;;;;;;;;;;;147249:172;145347:103;;;;;;;;;;-1:-1:-1;145347:103:0;;;;;:::i;:::-;;:::i;147425:126::-;;;;;;;;;;-1:-1:-1;147425:126:0;;;;;:::i;:::-;147524:10;;147492:7;147514:21;;;:9;:21;;;;;;;;-1:-1:-1;;;;;147514:31:0;;;;;;;;;;;147425:126;100315:104;;;;;;;;;;;;;:::i;157538:130::-;;;;;;;;;;-1:-1:-1;157538:130:0;;;;;:::i;:::-;;:::i;152622:140::-;;;:::i;158224:176::-;;;;;;;;;;-1:-1:-1;158224:176:0;;;;;:::i;:::-;;:::i;148330:111::-;;;;;;;;;;-1:-1:-1;148330:111:0;;;;;:::i;:::-;;:::i;138073:135::-;;;;;;;;;;-1:-1:-1;138073:135:0;;;;;:::i;:::-;138181:10;138166:26;;;;:14;:26;;;;;:34;138073:135;160395:117;;;;;;;;;;-1:-1:-1;160395:117:0;;;;;:::i;:::-;;:::i;134924:48::-;;;;;;;;;;-1:-1:-1;134924:48:0;;;;;:::i;:::-;;;;;;;;;;;;;;147596:106;;;;;;;;;;-1:-1:-1;147688:7:0;;147652;147674:22;;;:13;:22;;;;;;147596:106;;142285:43;;;;;;;;;;-1:-1:-1;142285:43:0;;;;;:::i;:::-;;;;;;;;;;;;;;158094:122;;;;;;;;;;-1:-1:-1;158094:122:0;;;;;:::i;:::-;;:::i;158923:228::-;;;;;;;;;;-1:-1:-1;158923:228:0;;;;;:::i;:::-;;:::i;147726:121::-;;;;;;;;;;-1:-1:-1;147726:121:0;;;;;:::i;:::-;;:::i;142090:47::-;;;;;;;;;;-1:-1:-1;142090:47:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;148928:101;;;;;;;;;;-1:-1:-1;148928:101:0;;;;;:::i;:::-;;:::i;146687:107::-;;;;;;;;;;-1:-1:-1;146687:107:0;;;;;:::i;:::-;;:::i;146410:124::-;;;;;;;;;;-1:-1:-1;146410:124:0;;;;;:::i;:::-;;:::i;149604:330::-;;;;;;;;;;-1:-1:-1;149604:330:0;;;;;:::i;:::-;;:::i;124958:428::-;;;;;;;;;;-1:-1:-1;124958:428:0;;;;;:::i;:::-;;:::i;141419:24::-;;;;;;;;;;;;;;;;141534:25;;;;;;;;;;;;;;;;146552:103;;;;;;;;;;-1:-1:-1;146552:103:0;;;;;:::i;:::-;;:::i;149331:131::-;;;;;;;;;;-1:-1:-1;149331:131:0;;;;;:::i;:::-;;:::i;141564:25::-;;;;;;;;;;;;;;;;150243:784;;;;;;:::i;:::-;;:::i;145912:111::-;;;;;;;;;;-1:-1:-1;145912:111:0;;;;;:::i;:::-;;:::i;148014:137::-;;;;;;;;;;-1:-1:-1;148014:137:0;;;;;:::i;:::-;;:::i;144465:113::-;;;;;;;;;;;;;:::i;138400:309::-;;;;;;;;;;-1:-1:-1;138400:309:0;;;;;:::i;:::-;;:::i;141380:34::-;;;;;;;;;;;;;;;;142142:47;;;;;;;;;;-1:-1:-1;142142:47:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;124211:461;;;;;;;;;;-1:-1:-1;124211:461:0;;;;;:::i;:::-;;:::i;118205:201::-;;;;;;;;;;-1:-1:-1;118205:201:0;;;;;:::i;:::-;;:::i;129466:43::-;;;;;;;;;;-1:-1:-1;129466:43:0;;;;;;;;150001:220;;;;;;;;;;-1:-1:-1;150001:220:0;;;;;:::i;:::-;;:::i;145610:121::-;;;;;;;;;;-1:-1:-1;145610:121:0;;;;;:::i;:::-;;:::i;159389:175::-;;;;;;;;;;-1:-1:-1;159389:175:0;;;;;:::i;:::-;;:::i;159761:181::-;159865:16;159906:28;:26;:28::i;:::-;159899:35;;159761:181;:::o;144257:179::-;144374:4;144394:36;144418:11;144394:23;:36::i;:::-;144387:43;144257:179;-1:-1:-1;;144257:179:0:o;160058:105::-;125542:32;96316:10;125542:18;:32::i;:::-;137718:3;:35;;-1:-1:-1;;;;;;137718:35:0;-1:-1:-1;;;;;137718:35:0;;;;;160058:105;:::o;160136:19::-:1;160058:105:::0;:::o;146027:111::-;125542:32;96316:10;125542:18;:32::i;:::-;146108:10:::1;:24:::0;146027:111::o;144079:157::-;125542:32;96316:10;125542:18;:32::i;:::-;144186:44:::1;144205:9;144216:13;144186:18;:44::i;:::-;144079:157:::0;;:::o;100146:100::-;100200:13;100233:5;100226:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;100146:100;:::o;101701:311::-;101822:7;101869:16;101877:7;101869;:16::i;:::-;101847:113;;;;-1:-1:-1;;;101847:113:0;;13677:2:1;101847:113:0;;;13659:21:1;13716:2;13696:18;;;13689:30;13755:34;13735:18;;;13728:62;-1:-1:-1;;;13806:18:1;;;13799:45;13861:19;;101847:113:0;;;;;;;;;-1:-1:-1;101980:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;101980:24:0;;101701:311::o;158408:157::-;158504:8;129618:42;131540:45;:49;;;;:77;;-1:-1:-1;131593:24:0;;;;131540:77;131536:253;;;131639:67;;-1:-1:-1;;;131639:67:0;;131690:4;131639:67;;;14103:34:1;-1:-1:-1;;;;;14173:15:1;;14153:18;;;14146:43;129618:42:0;;131639;;14038:18:1;;131639:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;131634:144;;131734:28;;-1:-1:-1;;;131734:28:0;;-1:-1:-1;;;;;3188:32:1;;131734:28:0;;;3170:51:1;3143:18;;131734:28:0;3024:203:1;131634:144:0;158525:32:::1;158539:8;158549:7;158525:13;:32::i;:::-;158408:157:::0;;;:::o;157758:106::-;125542:32;96316:10;125542:18;:32::i;:::-;157834:15:::1;:24:::0;;-1:-1:-1;;;;;;157834:24:0::1;-1:-1:-1::0;;;;;157834:24:0;;;::::1;::::0;;;::::1;::::0;;157758:106::o;149059:103::-;149117:7;149155:1;149139:14;98258:13;;;98176:103;149139:14;:17;;;;:::i;159950:100::-;125542:32;96316:10;125542:18;:32::i;:::-;160026:8:::1;:16:::0;159950:100::o;115276:122::-;115337:7;115381:9;:7;:9::i;:::-;115364:14;:12;:14::i;156851:130::-;125542:32;96316:10;125542:18;:32::i;:::-;156941:3:::1;:12:::0;;-1:-1:-1;;;;;;156941:12:0::1;-1:-1:-1::0;;;;;156941:12:0;;;::::1;::::0;;;::::1;::::0;;;156960:7:::1;:15:::0;156851:130::o;157309:::-;125542:32;96316:10;125542:18;:32::i;:::-;157399:3:::1;:12:::0;;-1:-1:-1;;;;;;157399:12:0::1;-1:-1:-1::0;;;;;157399:12:0;;;::::1;::::0;;;::::1;::::0;;;157418:7:::1;:15:::0;157309:130::o;158573:163::-;158674:4;129618:42;130766:45;:49;;;;:77;;-1:-1:-1;130819:24:0;;;;130766:77;130762:567;;;131083:10;-1:-1:-1;;;;;131075:18:0;;;131071:85;;158691:37:::1;158710:4;158716:2;158720:7;158691:18;:37::i;:::-;131134:7:::0;;131071:85;131175:69;;-1:-1:-1;;;131175:69:0;;131226:4;131175:69;;;14103:34:1;131233:10:0;14153:18:1;;;14146:43;129618:42:0;;131175;;14038:18:1;;131175:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;131170:148;;131272:30;;-1:-1:-1;;;131272:30:0;;131291:10;131272:30;;;3170:51:1;3143:18;;131272:30:0;3024:203:1;131170:148:0;158691:37:::1;158710:4;158716:2;158720:7;158691:18;:37::i;:::-;158573:163:::0;;;;:::o;148447:118::-;125542:32;96316:10;125542:18;:32::i;:::-;148530:29:::1;148547:11;124024:7:::0;;124010:22;;;;:13;:22;;;;;:36;123935:119;142034:38;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;160221:115::-;117185:13;:11;:13::i;:::-;160298:30:::1;160317:10;160298:18;:30::i;156622:130::-:0;125542:32;96316:10;125542:18;:32::i;:::-;156712:3:::1;:12:::0;;-1:-1:-1;;;;;;156712:12:0::1;-1:-1:-1::0;;;;;156712:12:0;;;::::1;::::0;;;::::1;::::0;;;156731:7:::1;:15:::0;156622:130::o;93060:442::-;93157:7;93215:27;;;:17;:27;;;;;;;;93186:56;;;;;;;;;-1:-1:-1;;;;;93186:56:0;;;;;-1:-1:-1;;;93186:56:0;;;-1:-1:-1;;;;;93186:56:0;;;;;;;;93157:7;;93255:92;;-1:-1:-1;93306:29:0;;;;;;;;;93316:19;93306:29;-1:-1:-1;;;;;93306:29:0;;;;-1:-1:-1;;;93306:29:0;;-1:-1:-1;;;;;93306:29:0;;;;;93255:92;93397:23;;;;93359:21;;93868:5;;93384:36;;-1:-1:-1;;;;;93384:36:0;:10;:36;:::i;:::-;93383:58;;;;:::i;:::-;93462:16;;;;;-1:-1:-1;93060:442:0;;-1:-1:-1;;;;93060:442:0:o;148571:156::-;125542:32;96316:10;125542:18;:32::i;:::-;124160:23;;;;:13;:23;;;;;;:37;144079:157::o;151049:852::-;82042:21;:19;:21::i;:::-;151181:22:::1;::::0;;;:15:::1;:22;::::0;;;;;::::1;;151173:58;;;::::0;-1:-1:-1;;;151173:58:0;;15444:2:1;151173:58:0::1;::::0;::::1;15426:21:1::0;15483:2;15463:18;;;15456:30;15522:25;15502:18;;;15495:53;15565:18;;151173:58:0::1;15242:347:1::0;151173:58:0::1;151246:39;151260:10;151271:5;151278:6;151246:13;:39::i;:::-;151238:76;;;::::0;-1:-1:-1;;;151238:76:0;;15796:2:1;151238:76:0::1;::::0;::::1;15778:21:1::0;15835:2;15815:18;;;15808:30;-1:-1:-1;;;15854:18:1;;;15847:54;15918:18;;151238:76:0::1;15594:348:1::0;151238:76:0::1;151348:7;151329:15;;:26;;151321:81;;;::::0;-1:-1:-1;;;151321:81:0;;16149:2:1;151321:81:0::1;::::0;::::1;16131:21:1::0;16188:2;16168:18;;;16161:30;16227:34;16207:18;;;16200:62;-1:-1:-1;;;16278:18:1;;;16271:40;16328:19;;151321:81:0::1;15947:406:1::0;151321:81:0::1;151417:20;::::0;;;:13:::1;:20;::::0;;;;;:31;-1:-1:-1;151417:31:0::1;151409:84;;;::::0;-1:-1:-1;;;151409:84:0;;16560:2:1;151409:84:0::1;::::0;::::1;16542:21:1::0;16599:2;16579:18;;;16572:30;16638:34;16618:18;;;16611:62;-1:-1:-1;;;16689:18:1;;;16682:38;16737:19;;151409:84:0::1;16358:404:1::0;151409:84:0::1;151532:16;::::0;;;:9:::1;:16;::::0;;;;;;;151549:8:::1;:15:::0;;;;;;151532:33;;;;;;;151566:10:::1;151532:45:::0;;;;;;;;:55:::1;::::0;151580:7;;151532:55:::1;:::i;:::-;151508:20;::::0;;;:13:::1;:20;::::0;;;;;:79:::1;;151500:122;;;::::0;-1:-1:-1;;;151500:122:0;;17099:2:1;151500:122:0::1;::::0;::::1;17081:21:1::0;17138:2;17118:18;;;17111:30;17177:32;17157:18;;;17150:60;17227:18;;151500:122:0::1;16897:354:1::0;151500:122:0::1;151650:18;::::0;;;:11:::1;:18;::::0;;;;;:28:::1;::::0;151671:7;;151650:28:::1;:::i;:::-;151637:9;:41;151629:78;;;;-1:-1:-1::0;;;151629:78:0::1;;;;;;;:::i;:::-;151752:8;;151733:13;:11;:13::i;:::-;151723:23;::::0;:7;:23:::1;:::i;:::-;151722:39;;:56;;;-1:-1:-1::0;151765:8:0::1;::::0;:13;151722:56:::1;151714:81;;;;-1:-1:-1::0;;;151714:81:0::1;;;;;;;:::i;:::-;151802:16;::::0;;;:9:::1;:16;::::0;;;;;;;151819:8:::1;:15:::0;;;;;;151802:33;;;;;;;151836:10:::1;151802:45:::0;;;;;;;:56;;151851:7;;151802:16;:56:::1;::::0;151851:7;;151802:56:::1;:::i;:::-;::::0;;;-1:-1:-1;151865:30:0::1;::::0;-1:-1:-1;151875:10:0::1;151887:7:::0;151865:9:::1;:30::i;:::-;82086:20:::0;81480:1;82606:7;:22;82423:213;151925:667;82042:21;:19;:21::i;:::-;152015:19:::1;::::0;::::1;;152007:52;;;::::0;-1:-1:-1;;;152007:52:0;;18152:2:1;152007:52:0::1;::::0;::::1;18134:21:1::0;18191:2;18171:18;;;18164:30;-1:-1:-1;;;18210:18:1;;;18203:50;18270:18;;152007:52:0::1;17950:344:1::0;152007:52:0::1;152093:7;152074:15;;:26;;152066:78;;;::::0;-1:-1:-1;;;152066:78:0;;18501:2:1;152066:78:0::1;::::0;::::1;18483:21:1::0;18540:2;18520:18;;;18513:30;18579:34;18559:18;;;18552:62;-1:-1:-1;;;18630:18:1;;;18623:37;18677:19;;152066:78:0::1;18299:403:1::0;152066:78:0::1;152176:7;152159:13;;:24;;152151:74;;;::::0;-1:-1:-1;;;152151:74:0;;18909:2:1;152151:74:0::1;::::0;::::1;18891:21:1::0;18948:2;18928:18;;;18921:30;18987:34;18967:18;;;18960:62;-1:-1:-1;;;19038:18:1;;;19031:35;19083:19;;152151:74:0::1;18707:401:1::0;152151:74:0::1;152267:10;::::0;152257:21:::1;::::0;;;:9:::1;:21;::::0;;;;;;;152279:10:::1;152257:33:::0;;;;;;;;:43:::1;::::0;152293:7;;152257:43:::1;:::i;:::-;152240:13;;:60;;152232:100;;;::::0;-1:-1:-1;;;152232:100:0;;19315:2:1;152232:100:0::1;::::0;::::1;19297:21:1::0;19354:2;19334:18;;;19327:30;19393:29;19373:18;;;19366:57;19440:18;;152232:100:0::1;19113:351:1::0;152232:100:0::1;152374:7;152360:11;;:21;;;;:::i;:::-;152347:9;:34;152339:71;;;;-1:-1:-1::0;;;152339:71:0::1;;;;;;;:::i;:::-;152455:8;;152436:13;:11;:13::i;:::-;152426:23;::::0;:7;:23:::1;:::i;:::-;152425:39;;:56;;;-1:-1:-1::0;152468:8:0::1;::::0;:13;152425:56:::1;152417:81;;;;-1:-1:-1::0;;;152417:81:0::1;;;;;;;:::i;:::-;152515:10;::::0;152505:21:::1;::::0;;;:9:::1;:21;::::0;;;;;;;152527:10:::1;152505:33:::0;;;;;;;:44;;152542:7;;152505:21;:44:::1;::::0;152542:7;;152505:44:::1;:::i;:::-;::::0;;;-1:-1:-1;152556:30:0::1;::::0;-1:-1:-1;152566:10:0::1;152578:7:::0;152556:9:::1;:30::i;:::-;82086:20:::0;81480:1;82606:7;:22;82423:213;146142:111;125542:32;96316:10;125542:18;:32::i;:::-;146223:10:::1;:24:::0;146142:111::o;152828:2260::-;125542:32;96316:10;125542:18;:32::i;:::-;82042:21:::1;:19;:21::i;:::-;152914:3:::2;::::0;-1:-1:-1;;;;;152914:3:0::2;:17:::0;;::::2;::::0;:33:::2;;-1:-1:-1::0;152935:7:0::2;::::0;:12;::::2;152914:33;152913:56;;;-1:-1:-1::0;152952:3:0::2;::::0;-1:-1:-1;;;;;152952:3:0::2;:17:::0;152913:56:::2;152905:114;;;::::0;-1:-1:-1;;;152905:114:0;;19671:2:1;152905:114:0::2;::::0;::::2;19653:21:1::0;19710:2;19690:18;;;19683:30;19749:34;19729:18;;;19722:62;-1:-1:-1;;;19800:18:1;;;19793:44;19854:19;;152905:114:0::2;19469:410:1::0;152905:114:0::2;153035:3;::::0;-1:-1:-1;;;;;153035:3:0::2;:17:::0;;::::2;::::0;:33:::2;;-1:-1:-1::0;153056:7:0::2;::::0;:12;::::2;153035:33;153034:56;;;-1:-1:-1::0;153073:3:0::2;::::0;-1:-1:-1;;;;;153073:3:0::2;:17:::0;153034:56:::2;153026:114;;;::::0;-1:-1:-1;;;153026:114:0;;20086:2:1;153026:114:0::2;::::0;::::2;20068:21:1::0;20125:2;20105:18;;;20098:30;20164:34;20144:18;;;20137:62;-1:-1:-1;;;20215:18:1;;;20208:44;20269:19;;153026:114:0::2;19884:410:1::0;153026:114:0::2;153156:3;::::0;-1:-1:-1;;;;;153156:3:0::2;:17:::0;;::::2;::::0;:33:::2;;-1:-1:-1::0;153177:7:0::2;::::0;:12;::::2;153156:33;153155:56;;;-1:-1:-1::0;153194:3:0::2;::::0;-1:-1:-1;;;;;153194:3:0::2;:17:::0;153155:56:::2;153147:114;;;::::0;-1:-1:-1;;;153147:114:0;;20501:2:1;153147:114:0::2;::::0;::::2;20483:21:1::0;20540:2;20520:18;;;20513:30;20579:34;20559:18;;;20552:62;-1:-1:-1;;;20630:18:1;;;20623:44;20684:19;;153147:114:0::2;20299:410:1::0;153147:114:0::2;153277:3;::::0;-1:-1:-1;;;;;153277:3:0::2;:17:::0;;::::2;::::0;:33:::2;;-1:-1:-1::0;153298:7:0::2;::::0;:12;::::2;153277:33;153276:56;;;-1:-1:-1::0;153315:3:0::2;::::0;-1:-1:-1;;;;;153315:3:0::2;:17:::0;153276:56:::2;153268:114;;;::::0;-1:-1:-1;;;153268:114:0;;20916:2:1;153268:114:0::2;::::0;::::2;20898:21:1::0;20955:2;20935:18;;;20928:30;20994:34;20974:18;;;20967:62;-1:-1:-1;;;21045:18:1;;;21038:44;21099:19;;153268:114:0::2;20714:410:1::0;153268:114:0::2;153398:3;::::0;-1:-1:-1;;;;;153398:3:0::2;:17:::0;;::::2;::::0;:33:::2;;-1:-1:-1::0;153419:7:0::2;::::0;:12;::::2;153398:33;153397:56;;;-1:-1:-1::0;153436:3:0::2;::::0;-1:-1:-1;;;;;153436:3:0::2;:17:::0;153397:56:::2;153389:114;;;::::0;-1:-1:-1;;;153389:114:0;;21331:2:1;153389:114:0::2;::::0;::::2;21313:21:1::0;21370:2;21350:18;;;21343:30;21409:34;21389:18;;;21382:62;-1:-1:-1;;;21460:18:1;;;21453:44;21514:19;;153389:114:0::2;21129:410:1::0;153389:114:0::2;153519:3;::::0;-1:-1:-1;;;;;153519:3:0::2;:17:::0;;::::2;::::0;:33:::2;;-1:-1:-1::0;153540:7:0::2;::::0;:12;::::2;153519:33;153518:56;;;-1:-1:-1::0;153557:3:0::2;::::0;-1:-1:-1;;;;;153557:3:0::2;:17:::0;153518:56:::2;153510:114;;;::::0;-1:-1:-1;;;153510:114:0;;21746:2:1;153510:114:0::2;::::0;::::2;21728:21:1::0;21785:2;21765:18;;;21758:30;21824:34;21804:18;;;21797:62;-1:-1:-1;;;21875:18:1;;;21868:44;21929:19;;153510:114:0::2;21544:410:1::0;153510:114:0::2;153698:3;::::0;153653:21:::2;::::0;153631:19:::2;::::0;-1:-1:-1;;;;;153698:3:0::2;:17:::0;153695:174:::2;;153757:3;::::0;153789:7:::2;::::0;-1:-1:-1;;;;;153757:3:0;;::::2;::::0;153797:5:::2;::::0;153775:21:::2;::::0;:11;:21:::2;:::i;:::-;:27;;;;:::i;:::-;153749:59;::::0;::::2;::::0;;;;;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;153740:68;;;;;153827:2;153819:42;;;::::0;-1:-1:-1;;;153819:42:0;;22371:2:1;153819:42:0::2;::::0;::::2;22353:21:1::0;22410:2;22390:18;;;22383:30;22449:29;22429:18;;;22422:57;22496:18;;153819:42:0::2;22169:351:1::0;153819:42:0::2;153878:3;::::0;-1:-1:-1;;;;;153878:3:0::2;:17:::0;153875:174:::2;;153937:3;::::0;153969:7:::2;::::0;-1:-1:-1;;;;;153937:3:0;;::::2;::::0;153977:5:::2;::::0;153955:21:::2;::::0;:11;:21:::2;:::i;:::-;:27;;;;:::i;:::-;153929:59;::::0;::::2;::::0;;;;;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;153920:68;;;;;154007:2;153999:42;;;::::0;-1:-1:-1;;;153999:42:0;;22727:2:1;153999:42:0::2;::::0;::::2;22709:21:1::0;22766:2;22746:18;;;22739:30;22805:29;22785:18;;;22778:57;22852:18;;153999:42:0::2;22525:351:1::0;153999:42:0::2;154058:3;::::0;-1:-1:-1;;;;;154058:3:0::2;:17:::0;154055:174:::2;;154117:3;::::0;154149:7:::2;::::0;-1:-1:-1;;;;;154117:3:0;;::::2;::::0;154157:5:::2;::::0;154135:21:::2;::::0;:11;:21:::2;:::i;:::-;:27;;;;:::i;:::-;154109:59;::::0;::::2;::::0;;;;;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;154100:68;;;;;154187:2;154179:42;;;::::0;-1:-1:-1;;;154179:42:0;;23083:2:1;154179:42:0::2;::::0;::::2;23065:21:1::0;23122:2;23102:18;;;23095:30;23161:29;23141:18;;;23134:57;23208:18;;154179:42:0::2;22881:351:1::0;154179:42:0::2;154238:3;::::0;-1:-1:-1;;;;;154238:3:0::2;:17:::0;154235:174:::2;;154297:3;::::0;154329:7:::2;::::0;-1:-1:-1;;;;;154297:3:0;;::::2;::::0;154337:5:::2;::::0;154315:21:::2;::::0;:11;:21:::2;:::i;:::-;:27;;;;:::i;:::-;154289:59;::::0;::::2;::::0;;;;;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;154280:68;;;;;154367:2;154359:42;;;::::0;-1:-1:-1;;;154359:42:0;;23439:2:1;154359:42:0::2;::::0;::::2;23421:21:1::0;23478:2;23458:18;;;23451:30;23517:29;23497:18;;;23490:57;23564:18;;154359:42:0::2;23237:351:1::0;154359:42:0::2;154418:3;::::0;-1:-1:-1;;;;;154418:3:0::2;:17:::0;154415:174:::2;;154477:3;::::0;154509:7:::2;::::0;-1:-1:-1;;;;;154477:3:0;;::::2;::::0;154517:5:::2;::::0;154495:21:::2;::::0;:11;:21:::2;:::i;:::-;:27;;;;:::i;:::-;154469:59;::::0;::::2;::::0;;;;;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;154460:68;;;;;154547:2;154539:42;;;::::0;-1:-1:-1;;;154539:42:0;;23795:2:1;154539:42:0::2;::::0;::::2;23777:21:1::0;23834:2;23814:18;;;23807:30;23873:29;23853:18;;;23846:57;23920:18;;154539:42:0::2;23593:351:1::0;154539:42:0::2;154598:3;::::0;-1:-1:-1;;;;;154598:3:0::2;:17:::0;154595:174:::2;;154657:3;::::0;154689:7:::2;::::0;-1:-1:-1;;;;;154657:3:0;;::::2;::::0;154697:5:::2;::::0;154675:21:::2;::::0;:11;:21:::2;:::i;:::-;:27;;;;:::i;:::-;154649:59;::::0;::::2;::::0;;;;;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;154640:68;;;;;154727:2;154719:42;;;::::0;-1:-1:-1;;;154719:42:0;;24151:2:1;154719:42:0::2;::::0;::::2;24133:21:1::0;24190:2;24170:18;;;24163:30;24229:29;24209:18;;;24202:57;24276:18;;154719:42:0::2;23949:351:1::0;154719:42:0::2;154820:15;::::0;154789:21:::2;::::0;-1:-1:-1;;;;;;154820:15:0::2;:29:::0;154817:220:::2;;154903:15;::::0;154895:55:::2;::::0;-1:-1:-1;;;;;154903:15:0;;::::2;::::0;154933:11;;154895:55:::2;::::0;;;154933:11;154903:15;154895:55:::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;154886:64;;;;;154817:220;;;117345:7:::0;117372:6;-1:-1:-1;;;;;117372:6:0;-1:-1:-1;;;;;154982:21:0::2;155012:11;154982:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;154973:56:0;;-1:-1:-1;;154817:220:0::2;155051:2;155043:39;;;::::0;-1:-1:-1;;;155043:39:0;;24507:2:1;155043:39:0::2;::::0;::::2;24489:21:1::0;24546:2;24526:18;;;24519:30;24585:26;24565:18;;;24558:54;24629:18;;155043:39:0::2;24305:348:1::0;155043:39:0::2;152898:2190;;82086:20:::1;81480:1:::0;82606:7;:22;82423:213;82086:20:::1;152828:2260::o:0;158744:171::-;158849:4;129618:42;130766:45;:49;;;;:77;;-1:-1:-1;130819:24:0;;;;130766:77;130762:567;;;131083:10;-1:-1:-1;;;;;131075:18:0;;;131071:85;;158866:41:::1;158889:4;158895:2;158899:7;158866:22;:41::i;131071:85::-:0;131175:69;;-1:-1:-1;;;131175:69:0;;131226:4;131175:69;;;14103:34:1;131233:10:0;14153:18:1;;;14146:43;129618:42:0;;131175;;14038:18:1;;131175:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;131170:148;;131272:30;;-1:-1:-1;;;131272:30:0;;131291:10;131272:30;;;3170:51:1;3143:18;;131272:30:0;3024:203:1;131170:148:0;158866:41:::1;158889:4;158895:2;158899:7;158866:22;:41::i;155108:201::-:0;155195:10;155175:16;155183:7;155175;:16::i;:::-;-1:-1:-1;;;;;155175:30:0;;155167:59;;;;-1:-1:-1;;;155167:59:0;;24860:2:1;155167:59:0;;;24842:21:1;24899:2;24879:18;;;24872:30;-1:-1:-1;;;24918:18:1;;;24911:46;24974:18;;155167:59:0;24658:340:1;155167:59:0;155245:8;;;;;;;:17;155237:39;;;;-1:-1:-1;;;155237:39:0;;25205:2:1;155237:39:0;;;25187:21:1;25244:1;25224:18;;;25217:29;-1:-1:-1;;;25262:18:1;;;25255:39;25311:18;;155237:39:0;25003:332:1;155237:39:0;155287:14;155293:7;155287:5;:14::i;155338:98::-;125542:32;96316:10;125542:18;:32::i;:::-;155412:8:::1;:16:::0;;;::::1;;;;-1:-1:-1::0;;155412:16:0;;::::1;::::0;;;::::1;::::0;;155338:98::o;155477:481::-;155549:16;155574:23;155600:19;155610:8;155600:9;:19::i;:::-;155574:45;;155626:25;155668:15;-1:-1:-1;;;;;155654:30:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;155654:30:0;-1:-1:-1;155626:58:0;-1:-1:-1;155760:18:0;144012:1;155789:142;155844:1;155828:14;98258:13;;;98176:103;155828:14;:17;;;;:::i;:::-;155823:1;:23;155789:142;;;155877:18;;-1:-1:-1;;;155877:18:0;;;;;3698:25:1;;;155877:4:0;;:15;;3671:18:1;;155877::0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;155865:30:0;:8;-1:-1:-1;;;;;155865:30:0;;155862:61;;155922:1;155897:8;155906:12;;;;:::i;:::-;;;155897:22;;;;;;;;:::i;:::-;;;;;;:26;;;;;155862:61;155848:3;;;;:::i;:::-;;;;155789:142;;;-1:-1:-1;155944:8:0;;155477:481;-1:-1:-1;;;;155477:481:0:o;149222:103::-;125542:32;96316:10;125542:18;:32::i;:::-;149299:13:::1;:20;149315:4:::0;149299:13;:20:::1;:::i;157080:130::-:0;125542:32;96316:10;125542:18;:32::i;:::-;157170:3:::1;:12:::0;;-1:-1:-1;;;;;;157170:12:0::1;-1:-1:-1::0;;;;;157170:12:0;;;::::1;::::0;;;::::1;::::0;;;157189:7:::1;:15:::0;157080:130::o;145756:152::-;125542:32;96316:10;125542:18;:32::i;:::-;145854:15:::1;::::0;;;:8:::1;:15;::::0;;;;:26;;;145887:10:::1;:15:::0;;145901:1:::1;::::0;145854:15;145887::::1;::::0;145901:1;;145887:15:::1;:::i;:::-;::::0;;;-1:-1:-1;;;;145756:152:0:o;99543:222::-;99660:7;99686:13;99705:29;99726:7;99705:20;:29::i;:::-;-1:-1:-1;99685:49:0;99543:222;-1:-1:-1;;;99543:222:0:o;145206:107::-;125542:32;96316:10;125542:18;:32::i;:::-;145285:9:::1;:22:::0;145206:107::o;148733:156::-;125542:32;96316:10;125542:18;:32::i;:::-;124778:23;;;;:13;:23;;;;;;:37;144079:157::o;98991:490::-;99113:4;-1:-1:-1;;;;;99144:19:0;;99136:77;;;;-1:-1:-1;;;99136:77:0;;28274:2:1;99136:77:0;;;28256:21:1;28313:2;28293:18;;;28286:30;28352:34;28332:18;;;28325:62;-1:-1:-1;;;28403:18:1;;;28396:43;28456:19;;99136:77:0;28072:409:1;99136:77:0;99226:10;144012:1;99247:204;98258:13;;99278:1;:18;99247:204;;;99321:10;99329:1;99321:7;:10::i;:::-;99318:122;;;99364:10;99372:1;99364:7;:10::i;:::-;-1:-1:-1;;;;;99355:19:0;:5;-1:-1:-1;;;;;99355:19:0;;99351:74;;99398:7;;;:::i;:::-;;;99351:74;99298:3;;;:::i;:::-;;;99247:204;;;-1:-1:-1;99468:5:0;98991:490;-1:-1:-1;;98991:490:0:o;117947:103::-;117185:13;:11;:13::i;:::-;118012:30:::1;118039:1;118012:18;:30::i;159572:181::-:0;125542:32;96316:10;125542:18;:32::i;:::-;159704:41:::1;159734:10;159704:29;:41::i;137889:176::-:0;138002:7;134597:16;134605:7;134597;:16::i;:::-;-1:-1:-1;;;;;134583:30:0;:10;-1:-1:-1;;;;;134583:30:0;;134561:122;;;;-1:-1:-1;;;134561:122:0;;28688:2:1;134561:122:0;;;28670:21:1;28727:2;28707:18;;;28700:30;28766:34;28746:18;;;28739:62;-1:-1:-1;;;28817:18:1;;;28810:40;28867:19;;134561:122:0;28486:406:1;134561:122:0;-1:-1:-1;138027:22:0::1;::::0;;;:13:::1;:22;::::0;;;;;:30;137889:176::o;147867:100::-;125542:32;96316:10;125542:18;:32::i;:::-;147941:13:::1;:20:::0;147867:100::o;156025:267::-;156118:21;;-1:-1:-1;;;156118:21:0;;;;;3698:25:1;;;156094:7:0;;156118:4;;:12;;3671:18:1;;156118:21:0;;;;;;;;;;;;;;;;;;-1:-1:-1;156118:21:0;;;;;;;;-1:-1:-1;;156118:21:0;;;;;;;;;;;;:::i;:::-;;;156114:171;;-1:-1:-1;156248:1:0;;156025:267;-1:-1:-1;156025:267:0:o;156114:171::-;156025:267;;;:::o;111684:601::-;111753:16;111807:19;111841:22;111866:16;111876:5;111866:9;:16::i;:::-;111841:41;;111897:25;111939:14;-1:-1:-1;;;;;111925:29:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;111925:29:0;-1:-1:-1;111897:57:0;-1:-1:-1;144012:1:0;111969:265;112018:14;112003:11;:29;111969:265;;112062:10;112070:1;112062:7;:10::i;:::-;112058:161;;;112115:5;-1:-1:-1;;;;;112101:19:0;:10;112109:1;112101:7;:10::i;:::-;-1:-1:-1;;;;;112101:19:0;;112097:103;;112175:1;112149:8;112158:13;;;;;;112149:23;;;;;;;;:::i;:::-;;;;;;:27;;;;;112097:103;112034:3;;111969:265;;;-1:-1:-1;112255:8:0;111684:601;-1:-1:-1;;;;111684:601:0:o;148176:131::-;125542:32;96316:10;125542:18;:32::i;:::-;148271:22:::1;::::0;;;:15:::1;:22;::::0;;;;;:30;;-1:-1:-1;;148271:30:0::1;::::0;::::1;;::::0;;;::::1;::::0;;148176:131::o;156393:130::-;125542:32;96316:10;125542:18;:32::i;:::-;156483:3:::1;:12:::0;;-1:-1:-1;;;;;;156483:12:0::1;-1:-1:-1::0;;;;;156483:12:0;;;::::1;::::0;;;::::1;::::0;;;156502:7:::1;:15:::0;156393:130::o;146289:103::-;125542:32;96316:10;125542:18;:32::i;:::-;146364:11:::1;:22:::0;146289:103::o;145347:::-;125542:32;96316:10;125542:18;:32::i;:::-;145424:8:::1;:20:::0;145347:103::o;100315:104::-;100371:13;100404:7;100397:14;;;;;:::i;157538:130::-;125542:32;96316:10;125542:18;:32::i;:::-;157628:3:::1;:12:::0;;-1:-1:-1;;;;;;157628:12:0::1;-1:-1:-1::0;;;;;157628:12:0;;;::::1;::::0;;;::::1;::::0;;;157647:7:::1;:15:::0;157538:130::o;152622:140::-;125542:32;96316:10;125542:18;:32::i;:::-;82042:21:::1;:19;:21::i;:::-;152726:1:::2;152714:9;:13;152706:50;;;;-1:-1:-1::0;;;152706:50:0::2;;;;;;;:::i;:::-;82086:20:::1;81480:1:::0;82606:7;:22;82423:213;158224:176;158328:8;129618:42;131540:45;:49;;;;:77;;-1:-1:-1;131593:24:0;;;;131540:77;131536:253;;;131639:67;;-1:-1:-1;;;131639:67:0;;131690:4;131639:67;;;14103:34:1;-1:-1:-1;;;;;14173:15:1;;14153:18;;;14146:43;129618:42:0;;131639;;14038:18:1;;131639:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;131634:144;;131734:28;;-1:-1:-1;;;131734:28:0;;-1:-1:-1;;;;;3188:32:1;;131734:28:0;;;3170:51:1;3143:18;;131734:28:0;3024:203:1;131634:144:0;158349:43:::1;158373:8;158383;158349:23;:43::i;148330:111::-:0;125542:32;96316:10;125542:18;:32::i;:::-;148408:19:::1;:27:::0;;-1:-1:-1;;148408:27:0::1;::::0;::::1;;::::0;;;::::1;::::0;;148330:111::o;160395:117::-;117185:13;:11;:13::i;:::-;160473:31:::1;160493:10;160473:19;:31::i;158094:122::-:0;125542:32;96316:10;125542:18;:32::i;:::-;158176:24:::1;:32:::0;;-1:-1:-1;;158176:32:0::1;::::0;::::1;;::::0;;;::::1;::::0;;158094:122::o;158923:228::-;159074:4;129618:42;130766:45;:49;;;;:77;;-1:-1:-1;130819:24:0;;;;130766:77;130762:567;;;131083:10;-1:-1:-1;;;;;131075:18:0;;;131071:85;;159096:47:::1;159119:4;159125:2;159129:7;159138:4;159096:22;:47::i;:::-;131134:7:::0;;131071:85;131175:69;;-1:-1:-1;;;131175:69:0;;131226:4;131175:69;;;14103:34:1;131233:10:0;14153:18:1;;;14146:43;129618:42:0;;131175;;14038:18:1;;131175:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;131170:148;;131272:30;;-1:-1:-1;;;131272:30:0;;131291:10;131272:30;;;3170:51:1;3143:18;;131272:30:0;3024:203:1;131170:148:0;159096:47:::1;159119:4;159125:2;159129:7;159138:4;159096:22;:47::i;:::-;158923:228:::0;;;;;:::o;147726:121::-;125542:32;96316:10;125542:18;:32::i;:::-;147814:20:::1;::::0;;;:13:::1;:20;::::0;;;;;:27;147726:121::o;148928:101::-;125542:32;96316:10;125542:18;:32::i;:::-;149007:9:::1;:16;149019:4:::0;149007:9;:16:::1;:::i;146687:107::-:0;125542:32;96316:10;125542:18;:32::i;:::-;146765:8:::1;:23:::0;146687:107::o;146410:124::-;125542:32;96316:10;125542:18;:32::i;:::-;146499:18:::1;::::0;;;:11:::1;:18;::::0;;;;;:29;146410:124::o;149604:330::-;149678:13;149708:17;149716:8;149708:7;:17::i;:::-;149700:61;;;;-1:-1:-1;;;149700:61:0;;29099:2:1;149700:61:0;;;29081:21:1;29138:2;29118:18;;;29111:30;29177:33;29157:18;;;29150:61;29228:18;;149700:61:0;28897:355:1;149700:61:0;149771:21;149783:8;146925;;-1:-1:-1;146913:20:0;;146824:115;149771:21;149768:138;;;149835:17;:15;:17::i;:::-;149854:26;149871:8;149854:16;:26::i;:::-;149882:14;149818:79;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;149804:94;;149604:330;;;:::o;149768:138::-;149919:9;149912:16;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;149604:330;;;:::o;124958:428::-;125102:26;;-1:-1:-1;;30667:2:1;30663:15;;;30659:53;125102:26:0;;;30647:66:1;125059:4:0;;;;30729:12:1;;125102:26:0;;;;;;;;;;;;125092:37;;;;;;125076:53;;125145:9;125140:192;125164:6;:13;125160:1;:17;125140:192;;;125215:6;125222:1;125215:9;;;;;;;;:::i;:::-;;;;;;;125207:5;:17;:113;;125302:6;125309:1;125302:9;;;;;;;;:::i;:::-;;;;;;;125313:5;125285:34;;;;;;;;30909:19:1;;;30953:2;30944:12;;30937:28;30990:2;30981:12;;30752:247;125285:34:0;;;;;;;;;;;;;125275:45;;;;;;125207:113;;;125254:5;125261:6;125268:1;125261:9;;;;;;;;:::i;:::-;;;;;;;125237:34;;;;;;;;30909:19:1;;;30953:2;30944:12;;30937:28;30990:2;30981:12;;30752:247;125237:34:0;;;;;;;;;;;;;125227:45;;;;;;125207:113;125199:121;-1:-1:-1;125179:3:0;;;;:::i;:::-;;;;125140:192;;;-1:-1:-1;125358:20:0;;;;:13;:20;;;;;;125349:29;;-1:-1:-1;124958:428:0;;;;;:::o;146552:103::-;125542:32;96316:10;125542:18;:32::i;:::-;146627:11:::1;:22:::0;146552:103::o;149331:131::-;125542:32;96316:10;125542:18;:32::i;:::-;149422:14:::1;:34;149439:17:::0;149422:14;:34:::1;:::i;150243:784::-:0;82042:21;:19;:21::i;:::-;150395:25:::1;::::0;;;:15:::1;:25;::::0;;;;;::::1;;150387:61;;;::::0;-1:-1:-1;;;150387:61:0;;31206:2:1;150387:61:0::1;::::0;::::1;31188:21:1::0;31245:2;31225:18;;;31218:30;31284:25;31264:18;;;31257:53;31327:18;;150387:61:0::1;31004:347:1::0;150387:61:0::1;150463:51;150477:10;150488:8;150498:7;150507:6;150463:13;:51::i;:::-;150455:88;;;::::0;-1:-1:-1;;;150455:88:0;;15796:2:1;150455:88:0::1;::::0;::::1;15778:21:1::0;15835:2;15815:18;;;15808:30;-1:-1:-1;;;15854:18:1;;;15847:54;15918:18;;150455:88:0::1;15594:348:1::0;150455:88:0::1;150568:1;150558:7;:11;150550:39;;;::::0;-1:-1:-1;;;150550:39:0;;31558:2:1;150550:39:0::1;::::0;::::1;31540:21:1::0;31597:2;31577:18;;;31570:30;-1:-1:-1;;;31616:18:1;;;31609:45;31671:18;;150550:39:0::1;31356:339:1::0;150550:39:0::1;150615:7;150604;:18;;150596:71;;;::::0;-1:-1:-1;;;150596:71:0;;31902:2:1;150596:71:0::1;::::0;::::1;31884:21:1::0;31941:2;31921:18;;;31914:30;31980:34;31960:18;;;31953:62;-1:-1:-1;;;32031:18:1;;;32024:38;32079:19;;150596:71:0::1;31700:404:1::0;150596:71:0::1;150693:19;::::0;;;:9:::1;:19;::::0;;;;;;;150713:10:::1;150693:31:::0;;;;;;;;:41:::1;::::0;150727:7;;150693:41:::1;:::i;:::-;150682:7;:52;;150674:95;;;::::0;-1:-1:-1;;;150674:95:0;;17099:2:1;150674:95:0::1;::::0;::::1;17081:21:1::0;17138:2;17118:18;;;17111:30;17177:32;17157:18;;;17150:60;17227:18;;150674:95:0::1;16897:354:1::0;150674:95:0::1;150811:7;150797:11;;:21;;;;:::i;:::-;150784:9;:34;150776:71;;;;-1:-1:-1::0;;;150776:71:0::1;;;;;;;:::i;:::-;150892:8;;150873:13;:11;:13::i;:::-;150863:23;::::0;:7;:23:::1;:::i;:::-;150862:39;;:56;;;-1:-1:-1::0;150905:8:0::1;::::0;:13;150862:56:::1;150854:81;;;;-1:-1:-1::0;;;150854:81:0::1;;;;;;;:::i;:::-;150942:19;::::0;;;:9:::1;:19;::::0;;;;;;;150962:10:::1;150942:31:::0;;;;;;;:42;;150977:7;;150942:19;:42:::1;::::0;150977:7;;150942:42:::1;:::i;:::-;::::0;;;-1:-1:-1;150991:30:0::1;::::0;-1:-1:-1;151001:10:0::1;151013:7:::0;150991:9:::1;:30::i;:::-;82086:20:::0;81480:1;82606:7;:22;82423:213;145912:111;125542:32;96316:10;125542:18;:32::i;:::-;145993:10:::1;:24:::0;145912:111::o;148014:137::-;125542:32;96316:10;125542:18;:32::i;:::-;148112:25:::1;::::0;;;:15:::1;:25;::::0;;;;;:33;;-1:-1:-1;;148112:33:0::1;::::0;::::1;;::::0;;;::::1;::::0;;148014:137::o;144465:113::-;144519:13;144552:20;:18;:20::i;138400:309::-;138542:4;138568:27;138579:5;138586:8;138568:10;:27::i;:::-;:36;;138599:5;138568:36;138564:81;;-1:-1:-1;138628:5:0;138621:12;;138564:81;-1:-1:-1;;;;;102656:25:0;;;102627:4;102656:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;138662:39;138655:46;138400:309;-1:-1:-1;;;138400:309:0:o;124211:461::-;124376:35;;-1:-1:-1;;32286:2:1;32282:15;;;32278:53;124376:35:0;;;32266:66:1;32348:12;;;32341:28;;;124333:4:0;;;;32385:12:1;;124376:35:0;;;;;;;;;;;;124366:46;;;;;;124350:62;;124428:9;124423:192;124447:6;:13;124443:1;:17;124423:192;;;124498:6;124505:1;124498:9;;;;;;;;:::i;:::-;;;;;;;124490:5;:17;:113;;124585:6;124592:1;124585:9;;;;;;;;:::i;:::-;;;;;;;124596:5;124568:34;;;;;;;;30909:19:1;;;30953:2;30944:12;;30937:28;30990:2;30981:12;;30752:247;124568:34:0;;;;;;;;;;;;;124558:45;;;;;;124490:113;;;124537:5;124544:6;124551:1;124544:9;;;;;;;;:::i;:::-;;;;;;;124520:34;;;;;;;;30909:19:1;;;30953:2;30944:12;;30937:28;30990:2;30981:12;;30752:247;124520:34:0;;;;;;;;;;;;;124510:45;;;;;;124490:113;124482:121;-1:-1:-1;124462:3:0;;;;:::i;:::-;;;;124423:192;;;-1:-1:-1;124641:23:0;;;;:13;:23;;;;;;124632:32;;-1:-1:-1;124211:461:0;;;;;;:::o;118205:201::-;117185:13;:11;:13::i;:::-;-1:-1:-1;;;;;118294:22:0;::::1;118286:73;;;::::0;-1:-1:-1;;;118286:73:0;;32610:2:1;118286:73:0::1;::::0;::::1;32592:21:1::0;32649:2;32629:18;;;32622:30;32688:34;32668:18;;;32661:62;-1:-1:-1;;;32739:18:1;;;32732:36;32785:19;;118286:73:0::1;32408:402:1::0;118286:73:0::1;118370:28;118389:8;118370:18;:28::i;150001:220::-:0;125542:32;96316:10;125542:18;:32::i;:::-;150135:9:::1;;150116:13;:11;:13::i;:::-;150106:23;::::0;:7;:23:::1;:::i;:::-;150105:40;;:58;;;-1:-1:-1::0;150149:9:0::1;::::0;:14;150105:58:::1;150097:83;;;;-1:-1:-1::0;;;150097:83:0::1;;;;;;;:::i;:::-;150187:28;150197:8;150207:7;150187:9;:28::i;145610:121::-:0;125542:32;96316:10;125542:18;:32::i;:::-;145699:15:::1;::::0;;;:8:::1;:15;::::0;;;;;:26;145610:121::o;159389:175::-;125542:32;96316:10;125542:18;:32::i;:::-;159518:38:::1;159545:10;159518:26;:38::i;135729:183::-:0;135833:16;135874:30;:21;:28;:30::i;92790:215::-;92892:4;-1:-1:-1;;;;;;92916:41:0;;-1:-1:-1;;;92916:41:0;;:81;;;92961:36;92985:11;92961:23;:36::i;126299:370::-;-1:-1:-1;;;;;126393:21:0;;;;;;:10;:21;;;;;;;;126526:46;96316:10;126554:12;-1:-1:-1;;;;;126526:46:0;126569:2;126526:19;:46::i;:::-;126454:181;;;;;;;;:::i;:::-;;;;;;;;;;;;;126371:290;;;;;-1:-1:-1;;;126371:290:0;;;;;;;;:::i;94152:332::-;93868:5;-1:-1:-1;;;;;94255:33:0;;;;94247:88;;;;-1:-1:-1;;;94247:88:0;;33633:2:1;94247:88:0;;;33615:21:1;33672:2;33652:18;;;33645:30;33711:34;33691:18;;;33684:62;-1:-1:-1;;;33762:18:1;;;33755:40;33812:19;;94247:88:0;33431:406:1;94247:88:0;-1:-1:-1;;;;;94354:22:0;;94346:60;;;;-1:-1:-1;;;94346:60:0;;34044:2:1;94346:60:0;;;34026:21:1;34083:2;34063:18;;;34056:30;34122:27;34102:18;;;34095:55;34167:18;;94346:60:0;33842:349:1;94346:60:0;94441:35;;;;;;;;;-1:-1:-1;;;;;94441:35:0;;;;;;-1:-1:-1;;;;;94441:35:0;;;;;;;;;;-1:-1:-1;;;94419:57:0;;;;:19;:57;94152:332::o;114993:207::-;115086:12;73028:10;;;115067:4;73115:20;;;;;;;;;;;;-1:-1:-1;;;73092:4:0;73084:12;;73064:33;73115:27;:32;115083:69;;-1:-1:-1;115135:5:0;;114993:207;-1:-1:-1;114993:207:0:o;115083:69::-;115170:22;115184:7;115170:13;:22::i;139299:185::-;139412:27;139427:2;139431:7;139412:14;:27::i;:::-;139450:26;139464:2;139468:7;139450:13;:26::i;115469:346::-;98258:13;;115511:14;;;;;;115611:25;;115578:1;115612:19;115635:1;115611:25;:::i;:::-;115590:46;-1:-1:-1;115663:11:0;115649:159;115680:10;115676:1;:14;115649:159;;;115712:14;79662:20;;;115729:12;79662:20;;;;;;115779:17;79662:20;115779:9;:17::i;:::-;115769:27;;;;:::i;:::-;;;115697:111;115692:3;;;;;:::i;:::-;;;;115649:159;;;;115526:289;;115469:346;:::o;98377:121::-;98432:7;144012:1;98459:13;;:31;;;;:::i;102766:379::-;102975:41;96316:10;103008:7;102975:18;:41::i;:::-;102953:143;;;;-1:-1:-1;;;102953:143:0;;;;;;;:::i;:::-;103109:28;103119:4;103125:2;103129:7;103109:9;:28::i;117464:132::-;117345:7;117372:6;-1:-1:-1;;;;;117372:6:0;96316:10;117528:23;117520:68;;;;-1:-1:-1;;;117520:68:0;;34819:2:1;117520:68:0;;;34801:21:1;;;34838:18;;;34831:30;34897:34;34877:18;;;34870:62;34949:18;;117520:68:0;34617:356:1;125719:421:0;-1:-1:-1;;;;;125810:22:0;;;;;;:10;:22;;;;;;;;125809:23;125944:46;96316:10;125972:12;96236:98;125944:46;125872:194;;;;;;;;:::i;:::-;;;;;;;;;;;;;125787:305;;;;;-1:-1:-1;;;125787:305:0;;;;;;;;:::i;:::-;-1:-1:-1;;;;;;126103:22:0;;;;;:10;:22;;;;;:29;;-1:-1:-1;;126103:29:0;126128:4;126103:29;;;125719:421::o;82122:293::-;81524:1;82256:7;;:19;82248:63;;;;-1:-1:-1;;;82248:63:0;;35809:2:1;82248:63:0;;;35791:21:1;35848:2;35828:18;;;35821:30;35887:33;35867:18;;;35860:61;35938:18;;82248:63:0;35607:355:1;82248:63:0;81524:1;82389:7;:18;82122:293::o;106463:112::-;106540:27;106550:2;106554:8;106540:27;;;;;;;;;;;;:9;:27::i;103216:185::-;103354:39;103371:4;103377:2;103381:7;103354:39;;;;;;;;;;;;:16;:39::i;114359:321::-;114419:12;114434:16;114442:7;114434;:16::i;:::-;114419:31;;114523:25;:12;114540:7;114523:16;:25::i;:::-;114574:35;;114601:7;;114597:1;;-1:-1:-1;;;;;114574:35:0;;;;;114597:1;;114574:35;114622:50;114643:4;114657:1;114661:7;114670:1;114622:20;:50::i;99773:306::-;99851:13;99866:24;99910:16;99918:7;99910;:16::i;:::-;99902:73;;;;-1:-1:-1;;;99902:73:0;;36169:2:1;99902:73:0;;;36151:21:1;36208:2;36188:18;;;36181:30;36247:34;36227:18;;;36220:62;-1:-1:-1;;;36298:18:1;;;36291:42;36350:19;;99902:73:0;35967:408:1;99902:73:0;100005:22;100019:7;100005:13;:22::i;:::-;100046:25;;;;:7;:25;;;;;;-1:-1:-1;;;;;100046:25:0;;99986:41;;-1:-1:-1;99773:306:0;-1:-1:-1;;99773:306:0:o;118566:191::-;118640:16;118659:6;;-1:-1:-1;;;;;118676:17:0;;;-1:-1:-1;;;;;;118676:17:0;;;;;;118709:40;;118659:6;;;;;;;118709:40;;118640:16;118709:40;118629:128;118566:191;:::o;135508:213::-;135618:40;:21;135647:10;135618:28;:40::i;:::-;-1:-1:-1;135674:39:0;;-1:-1:-1;;;;;135674:39:0;;;135690:10;;135674:39;;;;;135508:213;:::o;138717:325::-;138866:20;138877:8;138866:10;:20::i;:::-;:41;;;-1:-1:-1;138890:17:0;;138866:41;138844:136;;;;-1:-1:-1;;;138844:136:0;;36582:2:1;138844:136:0;;;36564:21:1;36621:2;36601:18;;;36594:30;36660:34;36640:18;;;36633:62;-1:-1:-1;;;36711:18:1;;;36704:43;36764:19;;138844:136:0;36380:409:1;138844:136:0;138991:43;139015:8;139025;138991:23;:43::i;126146:147::-;126215:30;126234:10;126215:18;:30::i;:::-;-1:-1:-1;;;;;126263:22:0;;;;;:10;:22;;;;;126256:29;;-1:-1:-1;;126256:29:0;;;126146:147::o;103472:368::-;103661:41;96316:10;103694:7;103661:18;:41::i;:::-;103639:143;;;;-1:-1:-1;;;103639:143:0;;;;;;;:::i;:::-;103793:39;103807:4;103813:2;103817:7;103826:5;103793:13;:39::i;149501:97::-;149551:13;149579;149572:20;;;;;:::i;63704:716::-;63760:13;63811:14;63828:17;63839:5;63828:10;:17::i;:::-;63848:1;63828:21;63811:38;;63864:20;63898:6;-1:-1:-1;;;;;63887:18:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;63887:18:0;-1:-1:-1;63864:41:0;-1:-1:-1;64029:28:0;;;64045:2;64029:28;64086:288;-1:-1:-1;;64118:5:0;-1:-1:-1;;;64255:2:0;64244:14;;64239:30;64118:5;64226:44;64316:2;64307:11;;;-1:-1:-1;64337:21:0;64086:288;64337:21;-1:-1:-1;64395:6:0;63704:716;-1:-1:-1;;;63704:716:0:o;144604:567::-;144657:13;144680:16;;144725:32;144680:16;93868:5;144725:11;:32::i;:::-;144679:78;;;;144866:283;144978:33;144995:15;144978:16;:33::i;:::-;145053:51;145089:8;-1:-1:-1;;;;;145073:26:0;145101:2;145053:19;:51::i;:::-;144912:213;;;;;;;;;:::i;:::-;;;;;;;;;;;;;144866:13;:283::i;:::-;144797:361;;;;;;;;:::i;:::-;;;;;;;;;;;;;144775:390;;;;144604:567;:::o;136563:236::-;136686:4;136708:13;136724:20;136737:6;136724:12;:20::i;:::-;136708:36;;136762:29;136773:10;136785:5;136762:10;:29::i;:::-;136755:36;136563:236;-1:-1:-1;;;;136563:236:0:o;135295:205::-;135402:37;:21;135428:10;135402:25;:37::i;:::-;-1:-1:-1;135455:37:0;;-1:-1:-1;;;;;135455:37:0;;;135469:10;;135455:37;;;;;135295:205;:::o;35394:310::-;35457:16;35486:22;35511:19;35519:3;35511:7;:19::i;139943:288::-;140073:4;-1:-1:-1;;;;;;140115:55:0;;-1:-1:-1;;;140115:55:0;;:108;;;140187:36;140211:11;140187:23;:36::i;64836:447::-;64911:13;64937:19;64969:10;64973:6;64969:1;:10;:::i;:::-;:14;;64982:1;64969:14;:::i;:::-;-1:-1:-1;;;;;64959:25:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;64959:25:0;;64937:47;;-1:-1:-1;;;64995:6:0;65002:1;64995:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;64995:15:0;;;;;;;;;-1:-1:-1;;;65021:6:0;65028:1;65021:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;65021:15:0;;;;;;;;-1:-1:-1;65052:9:0;65064:10;65068:6;65064:1;:10;:::i;:::-;:14;;65077:1;65064:14;:::i;:::-;65052:26;;65047:131;65084:1;65080;:5;65047:131;;;-1:-1:-1;;;65128:5:0;65136:3;65128:11;65119:21;;;;;;;:::i;:::-;;;;65107:6;65114:1;65107:9;;;;;;;;:::i;:::-;;;;:33;-1:-1:-1;;;;;65107:33:0;;;;;;;;-1:-1:-1;65165:1:0;65155:11;;;;;65087:3;;;:::i;:::-;;;65047:131;;;-1:-1:-1;65196:10:0;;65188:55;;;;-1:-1:-1;;;65188:55:0;;38658:2:1;65188:55:0;;;38640:21:1;;;38677:18;;;38670:30;38736:34;38716:18;;;38709:62;38788:18;;65188:55:0;38456:356:1;105334:151:0;105399:4;105433:14;98258:13;;;98176:103;105433:14;105423:7;:24;:54;;;;-1:-1:-1;;144012:1:0;105451:26;;;105334:151::o;139050:241::-;-1:-1:-1;;;;;139158:16:0;;;139154:130;;139199:23;139210:7;139219:2;139199:10;:23::i;:::-;139191:81;;;;-1:-1:-1;;;139191:81:0;;39019:2:1;139191:81:0;;;39001:21:1;39058:2;39038:18;;;39031:30;39097:34;39077:18;;;39070:62;-1:-1:-1;;;39148:18:1;;;39141:43;39201:19;;139191:81:0;38817:409:1;101225:410:0;101306:13;101322:16;101330:7;101322;:16::i;:::-;101306:32;;101363:5;-1:-1:-1;;;;;101357:11:0;:2;-1:-1:-1;;;;;101357:11:0;;101349:60;;;;-1:-1:-1;;;101349:60:0;;39433:2:1;101349:60:0;;;39415:21:1;39472:2;39452:18;;;39445:30;39511:34;39491:18;;;39484:62;-1:-1:-1;;;39562:18:1;;;39555:34;39606:19;;101349:60:0;39231:400:1;101349:60:0;96316:10;-1:-1:-1;;;;;101444:21:0;;;;:62;;-1:-1:-1;101469:37:0;101486:5;96316:10;138400:309;:::i;101469:37::-;101422:171;;;;-1:-1:-1;;;101422:171:0;;39838:2:1;101422:171:0;;;39820:21:1;39877:2;39857:18;;;39850:30;39916:34;39896:18;;;39889:62;39987:29;39967:18;;;39960:57;40034:19;;101422:171:0;39636:423:1;101422:171:0;101606:21;101615:2;101619:7;101606:8;:21::i;115882:177::-;115934:13;115984:56;115998:4;;115984:56;;-1:-1:-1;;116035:5:0;;116030:10;;;;116039:1;116004:7;115984:56;;105652:448;105781:4;105825:16;105833:7;105825;:16::i;:::-;105803:113;;;;-1:-1:-1;;;105803:113:0;;40266:2:1;105803:113:0;;;40248:21:1;40305:2;40285:18;;;40278:30;40344:34;40324:18;;;40317:62;-1:-1:-1;;;40395:18:1;;;40388:45;40450:19;;105803:113:0;40064:411:1;105803:113:0;105927:13;105943:16;105951:7;105943;:16::i;:::-;105927:32;;105989:5;-1:-1:-1;;;;;105978:16:0;:7;-1:-1:-1;;;;;105978:16:0;;:64;;;;106035:7;-1:-1:-1;;;;;106011:31:0;:20;106023:7;106011:11;:20::i;:::-;-1:-1:-1;;;;;106011:31:0;;105978:64;:113;;;;106059:32;106076:5;106083:7;106059:16;:32::i;108075:1057::-;108200:13;108215:24;108243:29;108264:7;108243:20;:29::i;:::-;108199:73;;;;108316:4;-1:-1:-1;;;;;108307:13:0;:5;-1:-1:-1;;;;;108307:13:0;;108285:107;;;;-1:-1:-1;;;108285:107:0;;40682:2:1;108285:107:0;;;40664:21:1;40721:2;40701:18;;;40694:30;40760:34;40740:18;;;40733:62;-1:-1:-1;;;40811:18:1;;;40804:42;40863:19;;108285:107:0;40480:408:1;108285:107:0;-1:-1:-1;;;;;108411:16:0;;108403:68;;;;-1:-1:-1;;;108403:68:0;;41095:2:1;108403:68:0;;;41077:21:1;41134:2;41114:18;;;41107:30;41173:34;41153:18;;;41146:62;-1:-1:-1;;;41224:18:1;;;41217:37;41271:19;;108403:68:0;40893:403:1;108403:68:0;108592:29;108609:1;108613:7;108592:8;:29::i;:::-;108637:25;108665:11;:7;108675:1;108665:11;:::i;:::-;73037:1;73028:10;;;72994:4;73115:20;;;108693:10;73115:20;;;;;;73028:10;;-1:-1:-1;;;;73092:4:0;73084:12;;73064:33;73115:27;:32;;;108692:87;;-1:-1:-1;98258:13:0;;108745:17;:34;108692:87;108689:210;;;108806:26;;;;:7;:26;;;;;:33;;-1:-1:-1;;;;;;108806:33:0;-1:-1:-1;;;;;108806:33:0;;;;;108854;-1:-1:-1;108806:26:0;108854:14;:33::i;:::-;108911:16;;;;:7;:16;;;;;:21;;-1:-1:-1;;;;;;108911:21:0;-1:-1:-1;;;;;108911:21:0;;;;;108946:27;;;108943:82;;108990:23;:10;109005:7;108990:14;:23::i;:::-;109061:7;109057:2;-1:-1:-1;;;;;109042:27:0;109051:4;-1:-1:-1;;;;;109042:27:0;;;;;;;;;;;109082:42;109103:4;109109:2;109113:7;109122:1;109082:20;:42::i;:::-;108188:944;;;108075:1057;;;:::o;106589:387::-;106720:19;106742:14;98258:13;;;98176:103;106742:14;106720:36;;106767:19;106773:2;106777:8;106767:5;:19::i;:::-;106819:68;106850:1;106854:2;106858:11;106871:8;106881:5;106819:22;:68::i;:::-;106797:171;;;;-1:-1:-1;;;106797:171:0;;;;;;;:::i;73541:204::-;73638:1;73629:10;;;73612:14;73709:20;;;;;;;;;;;;:28;;-1:-1:-1;;;73693:4:0;73685:12;;;73665:33;;;;73709:28;;;;;73541:204::o;139492:443::-;-1:-1:-1;;;;;139788:18:0;;;139784:144;;137851:22;;;;:13;:22;;;;;137844:29;139882:34;137769:112;111118:159;111181:24;111237:31;:10;111260:7;111237:22;:31::i;33718:158::-;33791:4;33815:53;33823:3;-1:-1:-1;;;;;33843:23:0;;33815:7;:53::i;136119:178::-;136226:4;136255:34;136266:10;136278;136255;:34::i;102084:330::-;96316:10;-1:-1:-1;;;;;102219:24:0;;;102211:65;;;;-1:-1:-1;;;102211:65:0;;41925:2:1;102211:65:0;;;41907:21:1;41964:2;41944:18;;;41937:30;42003;41983:18;;;41976:58;42051:18;;102211:65:0;41723:352:1;102211:65:0;96316:10;102289:32;;;;:18;:32;;;;;;;;-1:-1:-1;;;;;102289:42:0;;;;;;;;;;;;:53;;-1:-1:-1;;102289:53:0;;;;;;;;;;102358:48;;1203:41:1;;;102289:42:0;;96316:10;102358:48;;1176:18:1;102358:48:0;;;;;;;102084:330;;:::o;104722:357::-;104879:28;104889:4;104895:2;104899:7;104879:9;:28::i;:::-;104940:50;104963:4;104969:2;104973:7;104982:1;104984:5;104940:22;:50::i;60570:922::-;60623:7;;-1:-1:-1;;;60701:15:0;;60697:102;;-1:-1:-1;;;60737:15:0;;;-1:-1:-1;60781:2:0;60771:12;60697:102;60826:6;60817:5;:15;60813:102;;60862:6;60853:15;;;-1:-1:-1;60897:2:0;60887:12;60813:102;60942:6;60933:5;:15;60929:102;;60978:6;60969:15;;;-1:-1:-1;61013:2:0;61003:12;60929:102;61058:5;61049;:14;61045:99;;61093:5;61084:14;;;-1:-1:-1;61127:1:0;61117:11;61045:99;61171:5;61162;:14;61158:99;;61206:5;61197:14;;;-1:-1:-1;61240:1:0;61230:11;61158:99;61284:5;61275;:14;61271:99;;61319:5;61310:14;;;-1:-1:-1;61353:1:0;61343:11;61271:99;61397:5;61388;:14;61384:66;;61433:1;61423:11;61478:6;60570:922;-1:-1:-1;;60570:922:0:o;119548:1912::-;119606:13;119636:4;:11;119651:1;119636:16;119632:31;;-1:-1:-1;;119654:9:0;;;;;;;;;-1:-1:-1;119654:9:0;;;119548:1912::o;119632:31::-;119715:19;119737:12;;;;;;;;;;;;;;;;;119715:34;;119801:18;119847:1;119828:4;:11;119842:1;119828:15;;;;:::i;:::-;119827:21;;;;:::i;:::-;119822:27;;:1;:27;:::i;:::-;119801:48;-1:-1:-1;119932:20:0;119966:15;119801:48;119979:2;119966:15;:::i;:::-;-1:-1:-1;;;;;119955:27:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;119955:27:0;;119932:50;;120079:10;120071:6;120064:26;120174:1;120167:5;120163:13;120233:4;120284;120278:11;120269:7;120265:25;120380:2;120372:6;120368:15;120453:754;120472:6;120463:7;120460:19;120453:754;;;120572:1;120563:7;120559:15;120548:26;;120611:7;120605:14;120737:4;120729:5;120725:2;120721:14;120717:25;120707:8;120703:40;120697:47;120686:9;120678:67;120791:1;120780:9;120776:17;120763:30;;120870:4;120862:5;120858:2;120854:14;120850:25;120840:8;120836:40;120830:47;120819:9;120811:67;120924:1;120913:9;120909:17;120896:30;;121003:4;120995:5;120992:1;120987:14;120983:25;120973:8;120969:40;120963:47;120952:9;120944:67;121057:1;121046:9;121042:17;121029:30;;121136:4;121128:5;121116:25;121106:8;121102:40;121096:47;121085:9;121077:67;-1:-1:-1;121190:1:0;121175:17;120453:754;;;121280:1;121273:4;121267:11;121263:19;121301:1;121296:54;;;;121369:1;121364:52;;;;121256:160;;121296:54;-1:-1:-1;;;;;121312:17:0;;121305:43;121296:54;;121364:52;-1:-1:-1;;;;;121380:17:0;;121373:41;121256:160;-1:-1:-1;121446:6:0;;119548:1912;-1:-1:-1;;;;;;;;119548:1912:0:o;137398:253::-;-1:-1:-1;;;;;137532:22:0;;137503:7;137532:22;;;:14;:22;;;;;;:26;137528:88;;-1:-1:-1;;;;;;137582:22:0;;;;;:14;:22;;;;;;;137398:253::o;137528:88::-;-1:-1:-1;;137635:8:0;;;137398:253::o;136807:293::-;136956:14;;136929:4;;136956:14;;136951:59;;-1:-1:-1;136994:4:0;136987:11;;136951:59;137029:27;137045:10;137029:15;:27::i;:::-;:63;;;-1:-1:-1;137060:3:0;;:32;;-1:-1:-1;;;137060:32:0;;-1:-1:-1;;;;;4825:32:1;;;137060::0;;;4807:51:1;4874:18;;;4867:34;;;137060:3:0;;;;:13;;4780:18:1;;137060:32:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;33390:152::-;33460:4;33484:50;33489:3;-1:-1:-1;;;;;33509:23:0;;33484:4;:50::i;30565:111::-;30621:16;30657:3;:11;;30650:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30565:111;;;:::o;98572:355::-;98719:4;-1:-1:-1;;;;;;98761:40:0;;-1:-1:-1;;;98761:40:0;;:105;;-1:-1:-1;;;;;;;98818:48:0;;-1:-1:-1;;;98818:48:0;98761:105;:158;;;-1:-1:-1;;;;;;;;;;90451:40:0;;;98883:36;90342:157;136305:250;136429:4;136451:13;136467:33;136480:10;136492:7;136467:12;:33::i;109250:167::-;109325:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;109325:29:0;-1:-1:-1;;;;;109325:29:0;;;;;;;;:24;;109379:16;109325:24;109379:7;:16::i;:::-;-1:-1:-1;;;;;109370:39:0;;;;;;;;;;;109250:167;;:::o;106986:748::-;107084:19;107106:14;98258:13;;;98176:103;107106:14;107084:36;;107160:1;107149:8;:12;107141:62;;;;-1:-1:-1;;;107141:62:0;;42282:2:1;107141:62:0;;;42264:21:1;42321:2;42301:18;;;42294:30;42360:34;42340:18;;;42333:62;-1:-1:-1;;;42411:18:1;;;42404:35;42456:19;;107141:62:0;42080:401:1;107141:62:0;-1:-1:-1;;;;;107222:16:0;;107214:64;;;;-1:-1:-1;;;107214:64:0;;42688:2:1;107214:64:0;;;42670:21:1;42727:2;42707:18;;;42700:30;42766:34;42746:18;;;42739:62;-1:-1:-1;;;42817:18:1;;;42810:33;42860:19;;107214:64:0;42486:399:1;107214:64:0;107387:8;107370:13;;:25;;;;;;;:::i;:::-;;;;-1:-1:-1;;107406:20:0;;;;:7;:20;;;;;:25;;-1:-1:-1;;;;;;107406:25:0;-1:-1:-1;;;;;107406:25:0;;;;;107442:27;-1:-1:-1;107406:20:0;107442:14;:27::i;:::-;107480:59;107509:1;107513:2;107517:11;107530:8;107480:20;:59::i;:::-;107604:11;107584:142;107627:22;107641:8;107627:11;:22;:::i;:::-;107617:7;:32;107584:142;;;107681:33;;107706:7;;-1:-1:-1;;;;;107681:33:0;;;107698:1;;107681:33;;107698:1;;107681:33;107651:9;;;;:::i;:::-;;;;107584:142;;110071:1039;110258:6;-1:-1:-1;;;;;110281:13:0;;42499:19;:23;110277:826;;-1:-1:-1;110317:4:0;110358:12;110336:689;110382:23;110397:8;110382:12;:23;:::i;:::-;110372:7;:33;110336:689;;;110440:72;;-1:-1:-1;;;110440:72:0;;-1:-1:-1;;;;;110440:36:0;;;;;:72;;96316:10;;110491:4;;110497:7;;110506:5;;110440:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;110440:72:0;;;;;;;;-1:-1:-1;;110440:72:0;;;;;;;;;;;;:::i;:::-;;;110436:574;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110696:6;:13;110713:1;110696:18;110692:299;;110743:63;;-1:-1:-1;;;110743:63:0;;;;;;;:::i;110692:299::-;110933:6;110927:13;110918:6;110914:2;110910:15;110903:38;110436:574;110564:1;:56;;;;-1:-1:-1;;;;;;;110569:51:0;;-1:-1:-1;;;110569:51:0;110564:56;110560:60;;110513:127;110407:9;;;;:::i;:::-;;;;110336:689;;;;111039:8;;110277:826;-1:-1:-1;111087:4:0;110277:826;110071:1039;;;;;;;:::o;78312:1234::-;78452:1;78443:10;;;78394:19;78609:20;;;;;;;;;;;78394:19;;78443:10;78533:4;78525:12;;;;78714:18;;;78707:26;78786:6;;78783:756;;78884:22;:2;:20;:22::i;:::-;78869:37;;:11;:37;78863:1;78853:6;:11;;78852:55;78838:69;;78783:756;;;79007:1;78998:6;:10;78990:75;;;;-1:-1:-1;;;78990:75:0;;43840:2:1;78990:75:0;;;43822:21:1;43879:2;43859:18;;;43852:30;43918:34;43898:18;;;43891:62;-1:-1:-1;;;43969:18:1;;;43962:50;44029:19;;78990:75:0;43638:416:1;78990:75:0;-1:-1:-1;;;79117:8:0;;;79248:12;:20;;;;;;;;;;;79117:8;;-1:-1:-1;79308:6:0;;79305:207;;79414:22;:2;:20;:22::i;:::-;79407:3;:29;79390:47;;79401:1;79391:6;:11;;79390:47;79376:61;;79464:5;;79305:207;78959:569;;;78415:1131;;;78312:1234;;;;:::o;27711:1420::-;27777:4;27916:19;;;:12;;;:19;;;;;;27952:15;;27948:1176;;28327:21;28351:14;28364:1;28351:10;:14;:::i;:::-;28400:18;;28327:38;;-1:-1:-1;28380:17:0;;28400:22;;28421:1;;28400:22;:::i;:::-;28380:42;;28456:13;28443:9;:26;28439:405;;28490:17;28510:3;:11;;28522:9;28510:22;;;;;;;;:::i;:::-;;;;;;;;;28490:42;;28664:9;28635:3;:11;;28647:13;28635:26;;;;;;;;:::i;:::-;;;;;;;;;;;;:38;;;;28749:23;;;:12;;;:23;;;;;:36;;;28439:405;28925:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;29020:3;:12;;:19;29033:5;29020:19;;;;;;;;;;;29013:26;;;29063:4;29056:11;;;;;;;27948:1176;29107:5;29100:12;;;;;135920:191;136032:4;136061:42;:21;136092:10;-1:-1:-1;;;;;34096:23:0;;34042:4;29314:19;;;:12;;;:19;;;;;;:24;;34066:55;29217:129;27121:414;27184:4;29314:19;;;:12;;;:19;;;;;;27201:327;;-1:-1:-1;27244:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;27427:18;;27405:19;;;:12;;;:19;;;;;;:40;;;;27460:11;;27201:327;-1:-1:-1;27511:5:0;27504:12;;137108:282;137230:7;137259:22;;;:13;:22;;;;;;:26;137255:88;;-1:-1:-1;137309:22:0;;;;:13;:22;;;;;;137302:29;;137255:88;137362:20;137375:6;137362:12;:20::i;70511:201::-;70573:5;70629:16;;;;;;;;;;;;;;;;;70685:3;69027:64;70647:18;70662:2;70647:14;:18::i;:::-;:33;70646:42;;70629:60;;;;;;;;:::i;:::-;;;;;;;;70511:201;-1:-1:-1;;70511:201:0:o;69738:169::-;69797:7;69830:1;69825:2;:6;69817:15;;;;;;-1:-1:-1;69881:1:0;:6;;;69875:13;;69738:169::o;14:658:1:-;185:2;237:21;;;307:13;;210:18;;;329:22;;;156:4;;185:2;408:15;;;;382:2;367:18;;;156:4;451:195;465:6;462:1;459:13;451:195;;;530:13;;-1:-1:-1;;;;;526:39:1;514:52;;621:15;;;;586:12;;;;562:1;480:9;451:195;;;-1:-1:-1;663:3:1;;14:658;-1:-1:-1;;;;;;14:658:1:o;677:131::-;-1:-1:-1;;;;;;751:32:1;;741:43;;731:71;;798:1;795;788:12;813:245;871:6;924:2;912:9;903:7;899:23;895:32;892:52;;;940:1;937;930:12;892:52;979:9;966:23;998:30;1022:5;998:30;:::i;1255:131::-;-1:-1:-1;;;;;1330:31:1;;1320:42;;1310:70;;1376:1;1373;1366:12;1391:247;1450:6;1503:2;1491:9;1482:7;1478:23;1474:32;1471:52;;;1519:1;1516;1509:12;1471:52;1558:9;1545:23;1577:31;1602:5;1577:31;:::i;1643:180::-;1702:6;1755:2;1743:9;1734:7;1730:23;1726:32;1723:52;;;1771:1;1768;1761:12;1723:52;-1:-1:-1;1794:23:1;;1643:180;-1:-1:-1;1643:180:1:o;1828:435::-;1895:6;1903;1956:2;1944:9;1935:7;1931:23;1927:32;1924:52;;;1972:1;1969;1962:12;1924:52;2011:9;1998:23;2030:31;2055:5;2030:31;:::i;:::-;2080:5;-1:-1:-1;2137:2:1;2122:18;;2109:32;-1:-1:-1;;;;;2172:40:1;;2160:53;;2150:81;;2227:1;2224;2217:12;2150:81;2250:7;2240:17;;;1828:435;;;;;:::o;2268:250::-;2353:1;2363:113;2377:6;2374:1;2371:13;2363:113;;;2453:11;;;2447:18;2434:11;;;2427:39;2399:2;2392:10;2363:113;;;-1:-1:-1;;2510:1:1;2492:16;;2485:27;2268:250::o;2523:271::-;2565:3;2603:5;2597:12;2630:6;2625:3;2618:19;2646:76;2715:6;2708:4;2703:3;2699:14;2692:4;2685:5;2681:16;2646:76;:::i;:::-;2776:2;2755:15;-1:-1:-1;;2751:29:1;2742:39;;;;2783:4;2738:50;;2523:271;-1:-1:-1;;2523:271:1:o;2799:220::-;2948:2;2937:9;2930:21;2911:4;2968:45;3009:2;2998:9;2994:18;2986:6;2968:45;:::i;3232:315::-;3300:6;3308;3361:2;3349:9;3340:7;3336:23;3332:32;3329:52;;;3377:1;3374;3367:12;3329:52;3416:9;3403:23;3435:31;3460:5;3435:31;:::i;:::-;3485:5;3537:2;3522:18;;;;3509:32;;-1:-1:-1;;;3232:315:1:o;3734:456::-;3811:6;3819;3827;3880:2;3868:9;3859:7;3855:23;3851:32;3848:52;;;3896:1;3893;3886:12;3848:52;3935:9;3922:23;3954:31;3979:5;3954:31;:::i;:::-;4004:5;-1:-1:-1;4061:2:1;4046:18;;4033:32;4074:33;4033:32;4074:33;:::i;:::-;3734:456;;4126:7;;-1:-1:-1;;;4180:2:1;4165:18;;;;4152:32;;3734:456::o;4380:248::-;4448:6;4456;4509:2;4497:9;4488:7;4484:23;4480:32;4477:52;;;4525:1;4522;4515:12;4477:52;-1:-1:-1;;4548:23:1;;;4618:2;4603:18;;;4590:32;;-1:-1:-1;4380:248:1:o;5165:127::-;5226:10;5221:3;5217:20;5214:1;5207:31;5257:4;5254:1;5247:15;5281:4;5278:1;5271:15;5297:275;5368:2;5362:9;5433:2;5414:13;;-1:-1:-1;;5410:27:1;5398:40;;-1:-1:-1;;;;;5453:34:1;;5489:22;;;5450:62;5447:88;;;5515:18;;:::i;:::-;5551:2;5544:22;5297:275;;-1:-1:-1;5297:275:1:o;5577:712::-;5631:5;5684:3;5677:4;5669:6;5665:17;5661:27;5651:55;;5702:1;5699;5692:12;5651:55;5738:6;5725:20;5764:4;-1:-1:-1;;;;;5783:2:1;5780:26;5777:52;;;5809:18;;:::i;:::-;5855:2;5852:1;5848:10;5878:28;5902:2;5898;5894:11;5878:28;:::i;:::-;5940:15;;;6010;;;6006:24;;;5971:12;;;;6042:15;;;6039:35;;;6070:1;6067;6060:12;6039:35;6106:2;6098:6;6094:15;6083:26;;6118:142;6134:6;6129:3;6126:15;6118:142;;;6200:17;;6188:30;;6151:12;;;;6238;;;;6118:142;;;6278:5;5577:712;-1:-1:-1;;;;;;;5577:712:1:o;6294:484::-;6396:6;6404;6412;6465:2;6453:9;6444:7;6440:23;6436:32;6433:52;;;6481:1;6478;6471:12;6433:52;6517:9;6504:23;6494:33;;6574:2;6563:9;6559:18;6546:32;6536:42;;6629:2;6618:9;6614:18;6601:32;-1:-1:-1;;;;;6648:6:1;6645:30;6642:50;;;6688:1;6685;6678:12;6642:50;6711:61;6764:7;6755:6;6744:9;6740:22;6711:61;:::i;:::-;6701:71;;;6294:484;;;;;:::o;7263:118::-;7349:5;7342:13;7335:21;7328:5;7325:32;7315:60;;7371:1;7368;7361:12;7386:241;7442:6;7495:2;7483:9;7474:7;7470:23;7466:32;7463:52;;;7511:1;7508;7501:12;7463:52;7550:9;7537:23;7569:28;7591:5;7569:28;:::i;7632:632::-;7803:2;7855:21;;;7925:13;;7828:18;;;7947:22;;;7774:4;;7803:2;8026:15;;;;8000:2;7985:18;;;7774:4;8069:169;8083:6;8080:1;8077:13;8069:169;;;8144:13;;8132:26;;8213:15;;;;8178:12;;;;8105:1;8098:9;8069:169;;8269:407;8334:5;-1:-1:-1;;;;;8360:6:1;8357:30;8354:56;;;8390:18;;:::i;:::-;8428:57;8473:2;8452:15;;-1:-1:-1;;8448:29:1;8479:4;8444:40;8428:57;:::i;:::-;8419:66;;8508:6;8501:5;8494:21;8548:3;8539:6;8534:3;8530:16;8527:25;8524:45;;;8565:1;8562;8555:12;8524:45;8614:6;8609:3;8602:4;8595:5;8591:16;8578:43;8668:1;8661:4;8652:6;8645:5;8641:18;8637:29;8630:40;8269:407;;;;;:::o;8681:451::-;8750:6;8803:2;8791:9;8782:7;8778:23;8774:32;8771:52;;;8819:1;8816;8809:12;8771:52;8859:9;8846:23;-1:-1:-1;;;;;8884:6:1;8881:30;8878:50;;;8924:1;8921;8914:12;8878:50;8947:22;;9000:4;8992:13;;8988:27;-1:-1:-1;8978:55:1;;9029:1;9026;9019:12;8978:55;9052:74;9118:7;9113:2;9100:16;9095:2;9091;9087:11;9052:74;:::i;9137:309::-;9202:6;9210;9263:2;9251:9;9242:7;9238:23;9234:32;9231:52;;;9279:1;9276;9269:12;9231:52;9315:9;9302:23;9292:33;;9375:2;9364:9;9360:18;9347:32;9388:28;9410:5;9388:28;:::i;9451:315::-;9519:6;9527;9580:2;9568:9;9559:7;9555:23;9551:32;9548:52;;;9596:1;9593;9586:12;9548:52;9632:9;9619:23;9609:33;;9692:2;9681:9;9677:18;9664:32;9705:31;9730:5;9705:31;:::i;9771:382::-;9836:6;9844;9897:2;9885:9;9876:7;9872:23;9868:32;9865:52;;;9913:1;9910;9903:12;9865:52;9952:9;9939:23;9971:31;9996:5;9971:31;:::i;:::-;10021:5;-1:-1:-1;10078:2:1;10063:18;;10050:32;10091:30;10050:32;10091:30;:::i;10158:795::-;10253:6;10261;10269;10277;10330:3;10318:9;10309:7;10305:23;10301:33;10298:53;;;10347:1;10344;10337:12;10298:53;10386:9;10373:23;10405:31;10430:5;10405:31;:::i;:::-;10455:5;-1:-1:-1;10512:2:1;10497:18;;10484:32;10525:33;10484:32;10525:33;:::i;:::-;10577:7;-1:-1:-1;10631:2:1;10616:18;;10603:32;;-1:-1:-1;10686:2:1;10671:18;;10658:32;-1:-1:-1;;;;;10702:30:1;;10699:50;;;10745:1;10742;10735:12;10699:50;10768:22;;10821:4;10813:13;;10809:27;-1:-1:-1;10799:55:1;;10850:1;10847;10840:12;10799:55;10873:74;10939:7;10934:2;10921:16;10916:2;10912;10908:11;10873:74;:::i;:::-;10863:84;;;10158:795;;;;;;;:::o;10958:551::-;11060:6;11068;11076;11129:2;11117:9;11108:7;11104:23;11100:32;11097:52;;;11145:1;11142;11135:12;11097:52;11184:9;11171:23;11203:31;11228:5;11203:31;:::i;:::-;11253:5;-1:-1:-1;11305:2:1;11290:18;;11277:32;;-1:-1:-1;11360:2:1;11345:18;;11332:32;-1:-1:-1;;;;;11376:30:1;;11373:50;;;11419:1;11416;11409:12;11514:553;11625:6;11633;11641;11649;11702:3;11690:9;11681:7;11677:23;11673:33;11670:53;;;11719:1;11716;11709:12;11670:53;11755:9;11742:23;11732:33;;11812:2;11801:9;11797:18;11784:32;11774:42;;11863:2;11852:9;11848:18;11835:32;11825:42;;11918:2;11907:9;11903:18;11890:32;-1:-1:-1;;;;;11937:6:1;11934:30;11931:50;;;11977:1;11974;11967:12;11931:50;12000:61;12053:7;12044:6;12033:9;12029:22;12000:61;:::i;12072:388::-;12140:6;12148;12201:2;12189:9;12180:7;12176:23;12172:32;12169:52;;;12217:1;12214;12207:12;12169:52;12256:9;12243:23;12275:31;12300:5;12275:31;:::i;:::-;12325:5;-1:-1:-1;12382:2:1;12367:18;;12354:32;12395:33;12354:32;12395:33;:::i;12465:620::-;12576:6;12584;12592;12600;12653:3;12641:9;12632:7;12628:23;12624:33;12621:53;;;12670:1;12667;12660:12;12621:53;12709:9;12696:23;12728:31;12753:5;12728:31;:::i;:::-;12778:5;-1:-1:-1;12830:2:1;12815:18;;12802:32;;-1:-1:-1;12881:2:1;12866:18;;12853:32;;-1:-1:-1;12936:2:1;12921:18;;12908:32;-1:-1:-1;;;;;12952:30:1;;12949:50;;;12995:1;12992;12985:12;13090:380;13169:1;13165:12;;;;13212;;;13233:61;;13287:4;13279:6;13275:17;13265:27;;13233:61;13340:2;13332:6;13329:14;13309:18;13306:38;13303:161;;13386:10;13381:3;13377:20;13374:1;13367:31;13421:4;13418:1;13411:15;13449:4;13446:1;13439:15;13303:161;;13090:380;;;:::o;14200:245::-;14267:6;14320:2;14308:9;14299:7;14295:23;14291:32;14288:52;;;14336:1;14333;14326:12;14288:52;14368:9;14362:16;14387:28;14409:5;14387:28;:::i;14450:127::-;14511:10;14506:3;14502:20;14499:1;14492:31;14542:4;14539:1;14532:15;14566:4;14563:1;14556:15;14582:128;14649:9;;;14670:11;;;14667:37;;;14684:18;;:::i;14715:168::-;14788:9;;;14819;;14836:15;;;14830:22;;14816:37;14806:71;;14857:18;;:::i;15020:217::-;15060:1;15086;15076:132;;15130:10;15125:3;15121:20;15118:1;15111:31;15165:4;15162:1;15155:15;15193:4;15190:1;15183:15;15076:132;-1:-1:-1;15222:9:1;;15020:217::o;16767:125::-;16832:9;;;16853:10;;;16850:36;;;16866:18;;:::i;17256:348::-;17458:2;17440:21;;;17497:2;17477:18;;;17470:30;17536:26;17531:2;17516:18;;17509:54;17595:2;17580:18;;17256:348::o;17609:336::-;17811:2;17793:21;;;17850:2;17830:18;;;17823:30;-1:-1:-1;;;17884:2:1;17869:18;;17862:42;17936:2;17921:18;;17609:336::o;25340:251::-;25410:6;25463:2;25451:9;25442:7;25438:23;25434:32;25431:52;;;25479:1;25476;25469:12;25431:52;25511:9;25505:16;25530:31;25555:5;25530:31;:::i;25596:135::-;25635:3;25656:17;;;25653:43;;25676:18;;:::i;:::-;-1:-1:-1;25723:1:1;25712:13;;25596:135::o;25736:127::-;25797:10;25792:3;25788:20;25785:1;25778:31;25828:4;25825:1;25818:15;25852:4;25849:1;25842:15;25994:545;26096:2;26091:3;26088:11;26085:448;;;26132:1;26157:5;26153:2;26146:17;26202:4;26198:2;26188:19;26272:2;26260:10;26256:19;26253:1;26249:27;26243:4;26239:38;26308:4;26296:10;26293:20;26290:47;;;-1:-1:-1;26331:4:1;26290:47;26386:2;26381:3;26377:12;26374:1;26370:20;26364:4;26360:31;26350:41;;26441:82;26459:2;26452:5;26449:13;26441:82;;;26504:17;;;26485:1;26474:13;26441:82;;26715:1352;26841:3;26835:10;-1:-1:-1;;;;;26860:6:1;26857:30;26854:56;;;26890:18;;:::i;:::-;26919:97;27009:6;26969:38;27001:4;26995:11;26969:38;:::i;:::-;26963:4;26919:97;:::i;:::-;27071:4;;27135:2;27124:14;;27152:1;27147:663;;;;27854:1;27871:6;27868:89;;;-1:-1:-1;27923:19:1;;;27917:26;27868:89;-1:-1:-1;;26672:1:1;26668:11;;;26664:24;26660:29;26650:40;26696:1;26692:11;;;26647:57;27970:81;;27117:944;;27147:663;25941:1;25934:14;;;25978:4;25965:18;;-1:-1:-1;;27183:20:1;;;27301:236;27315:7;27312:1;27309:14;27301:236;;;27404:19;;;27398:26;27383:42;;27496:27;;;;27464:1;27452:14;;;;27331:19;;27301:236;;;27305:3;27565:6;27556:7;27553:19;27550:201;;;27626:19;;;27620:26;-1:-1:-1;;27709:1:1;27705:14;;;27721:3;27701:24;27697:37;27693:42;27678:58;27663:74;;27550:201;-1:-1:-1;;;;;27797:1:1;27781:14;;;27777:22;27764:36;;-1:-1:-1;26715:1352:1:o;29257:1256::-;29481:3;29519:6;29513:13;29545:4;29558:64;29615:6;29610:3;29605:2;29597:6;29593:15;29558:64;:::i;:::-;29685:13;;29644:16;;;;29707:68;29685:13;29644:16;29742:15;;;29707:68;:::i;:::-;29864:13;;29797:20;;;29837:1;;29902:36;29864:13;29902:36;:::i;:::-;29957:1;29974:18;;;30001:141;;;;30156:1;30151:337;;;;29967:521;;30001:141;-1:-1:-1;;30036:24:1;;30022:39;;30113:16;;30106:24;30092:39;;30081:51;;;-1:-1:-1;30001:141:1;;30151:337;30182:6;30179:1;30172:17;30230:2;30227:1;30217:16;30255:1;30269:169;30283:8;30280:1;30277:15;30269:169;;;30365:14;;30350:13;;;30343:37;30408:16;;;;30300:10;;30269:169;;;30273:3;;30469:8;30462:5;30458:20;30451:27;;29967:521;-1:-1:-1;30504:3:1;;29257:1256;-1:-1:-1;;;;;;;;;;29257:1256:1:o;32815:611::-;-1:-1:-1;;;33173:3:1;33166:23;33148:3;33218:6;33212:13;33234:74;33301:6;33297:1;33292:3;33288:11;33281:4;33273:6;33269:17;33234:74;:::i;:::-;-1:-1:-1;;;33367:1:1;33327:16;;;;33359:10;;;33352:41;-1:-1:-1;33417:2:1;33409:11;;32815:611;-1:-1:-1;32815:611:1:o;34196:416::-;34398:2;34380:21;;;34437:2;34417:18;;;34410:30;34476:34;34471:2;34456:18;;34449:62;-1:-1:-1;;;34542:2:1;34527:18;;34520:50;34602:3;34587:19;;34196:416::o;34978:624::-;-1:-1:-1;;;35336:3:1;35329:23;35311:3;35381:6;35375:13;35397:74;35464:6;35460:1;35455:3;35451:11;35444:4;35436:6;35432:17;35397:74;:::i;:::-;35534:34;35530:1;35490:16;;;;35522:10;;;35515:54;-1:-1:-1;35593:2:1;35585:11;;34978:624;-1:-1:-1;34978:624:1:o;36794:1050::-;37306:66;37301:3;37294:79;37276:3;37402:6;37396:13;37418:75;37486:6;37481:2;37476:3;37472:12;37465:4;37457:6;37453:17;37418:75;:::i;:::-;-1:-1:-1;;;37552:2:1;37512:16;;;37544:11;;;37537:71;37633:13;;37655:76;37633:13;37717:2;37709:11;;37702:4;37690:17;;37655:76;:::i;:::-;-1:-1:-1;;;37791:2:1;37750:17;;;;37783:11;;;37776:35;37835:2;37827:11;;36794:1050;-1:-1:-1;;;;36794:1050:1:o;37849:461::-;38111:31;38106:3;38099:44;38081:3;38172:6;38166:13;38188:75;38256:6;38251:2;38246:3;38242:12;38235:4;38227:6;38223:17;38188:75;:::i;:::-;38283:16;;;;38301:2;38279:25;;37849:461;-1:-1:-1;;37849:461:1:o;38315:136::-;38354:3;38382:5;38372:39;;38391:18;;:::i;:::-;-1:-1:-1;;;38427:18:1;;38315:136::o;41301:417::-;41503:2;41485:21;;;41542:2;41522:18;;;41515:30;41581:34;41576:2;41561:18;;41554:62;-1:-1:-1;;;41647:2:1;41632:18;;41625:51;41708:3;41693:19;;41301:417::o;42890:489::-;-1:-1:-1;;;;;43159:15:1;;;43141:34;;43211:15;;43206:2;43191:18;;43184:43;43258:2;43243:18;;43236:34;;;43306:3;43301:2;43286:18;;43279:31;;;43084:4;;43327:46;;43353:19;;43345:6;43327:46;:::i;:::-;43319:54;42890:489;-1:-1:-1;;;;;;42890:489:1:o;43384:249::-;43453:6;43506:2;43494:9;43485:7;43481:23;43477:32;43474:52;;;43522:1;43519;43512:12;43474:52;43554:9;43548:16;43573:30;43597:5;43573:30;:::i;44059:127::-;44120:10;44115:3;44111:20;44108:1;44101:31;44151:4;44148:1;44141:15;44175:4;44172:1;44165:15

Swarm Source

ipfs://df1a468af855e4daf5b4dd55626c27bcd477128fac9099d0973f297784be5713
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.