ETH Price: $3,472.37 (-0.56%)

Token

Beta Token (BETA)
 

Overview

Max Total Supply

1,000,000,000 BETA

Holders

2,121 ( -0.047%)

Market

Price

$0.05 @ 0.000013 ETH (-2.07%)

Onchain Market Cap

$46,699,590.00

Circulating Supply Market Cap

$40,090,636.00

Other Info

Token Contract (WITH 18 Decimals)

Balance
26,000.000023222086883175 BETA

Value
$1,214.19 ( ~0.349671466119835 Eth) [0.0026%]
0x26AC964322D40153AfFC104738339a2754CC348e
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Beta Finance is a cross-chain permissionless money market protocol for lending, borrowing, and shorting crypto. Beta Finance has created an integrated “1-Click” Short Tool to initiate, manage, and close short positions, as well as allow anyone to create money markets for a token automatically.

Market

Volume (24H):$6,640,574.00
Market Capitalization:$40,090,636.00
Circulating Supply:859,090,909.00 BETA
Market Data Source: Coinmarketcap

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
BetaToken

Compiler Version
v0.8.6+commit.11564f7e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-08-30
*/

// File: @openzeppelin/[email protected]/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: @openzeppelin/[email protected]/utils/Counters.sol

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
  struct Counter {
    // This variable should never be directly accessed by users of the library: interactions must be restricted to
    // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
    // this feature: see https://github.com/ethereum/solidity/issues/4637
    uint _value; // default: 0
  }

  function current(Counter storage counter) internal view returns (uint) {
    return counter._value;
  }

  function increment(Counter storage counter) internal {
    unchecked {
      counter._value += 1;
    }
  }

  function decrement(Counter storage counter) internal {
    uint value = counter._value;
    require(value > 0, 'Counter: decrement overflow');
    unchecked {
      counter._value = value - 1;
    }
  }

  function reset(Counter storage counter) internal {
    counter._value = 0;
  }
}

// File: @openzeppelin/[email protected]/utils/cryptography/ECDSA.sol

pragma solidity ^0.8.0;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
  /**
   * @dev Returns the address that signed a hashed message (`hash`) with
   * `signature`. This address can then be used for verification purposes.
   *
   * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
   * this function rejects them by requiring the `s` value to be in the lower
   * half order, and the `v` value to be either 27 or 28.
   *
   * IMPORTANT: `hash` _must_ be the result of a hash operation for the
   * verification to be secure: it is possible to craft signatures that
   * recover to arbitrary addresses for non-hashed data. A safe way to ensure
   * this is by receiving a hash of the original message (which may otherwise
   * be too long), and then calling {toEthSignedMessageHash} on it.
   *
   * Documentation for signature generation:
   * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
   * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
   */
  function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
    // Check the signature length
    // - case 65: r,s,v signature (standard)
    // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
    if (signature.length == 65) {
      bytes32 r;
      bytes32 s;
      uint8 v;
      // ecrecover takes the signature parameters, and the only way to get them
      // currently is to use assembly.
      assembly {
        r := mload(add(signature, 0x20))
        s := mload(add(signature, 0x40))
        v := byte(0, mload(add(signature, 0x60)))
      }
      return recover(hash, v, r, s);
    } else if (signature.length == 64) {
      bytes32 r;
      bytes32 vs;
      // ecrecover takes the signature parameters, and the only way to get them
      // currently is to use assembly.
      assembly {
        r := mload(add(signature, 0x20))
        vs := mload(add(signature, 0x40))
      }
      return recover(hash, r, vs);
    } else {
      revert('ECDSA: invalid signature length');
    }
  }

  /**
   * @dev Overload of {ECDSA-recover} that receives the `r` and `vs` short-signature fields separately.
   *
   * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
   *
   * _Available since v4.2._
   */
  function recover(
    bytes32 hash,
    bytes32 r,
    bytes32 vs
  ) internal pure returns (address) {
    bytes32 s;
    uint8 v;
    assembly {
      s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
      v := add(shr(255, vs), 27)
    }
    return recover(hash, v, r, s);
  }

  /**
   * @dev Overload of {ECDSA-recover} that receives the `v`, `r` and `s` signature fields separately.
   */
  function recover(
    bytes32 hash,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) internal pure returns (address) {
    // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
    // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
    // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
    // signatures from current libraries generate a unique signature with an s-value in the lower half order.
    //
    // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
    // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
    // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
    // these malleable signatures as well.
    require(
      uint(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
      "ECDSA: invalid signature 's' value"
    );
    require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value");

    // If the signature is valid (and not malleable), return the signer address
    address signer = ecrecover(hash, v, r, s);
    require(signer != address(0), 'ECDSA: invalid signature');

    return signer;
  }

  /**
   * @dev Returns an Ethereum Signed Message, created from a `hash`. This
   * produces hash corresponding to the one signed with the
   * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
   * JSON-RPC method as part of EIP-191.
   *
   * See {recover}.
   */
  function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
    // 32 is the length in bytes of hash,
    // enforced by the type signature above
    return keccak256(abi.encodePacked('\x19Ethereum Signed Message:\n32', hash));
  }

  /**
   * @dev Returns an Ethereum Signed Typed Data, created from a
   * `domainSeparator` and a `structHash`. This produces hash corresponding
   * to the one signed with the
   * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
   * JSON-RPC method as part of EIP-712.
   *
   * See {recover}.
   */
  function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash)
    internal
    pure
    returns (bytes32)
  {
    return keccak256(abi.encodePacked('\x19\x01', domainSeparator, structHash));
  }
}

// File: @openzeppelin/[email protected]/utils/cryptography/draft-EIP712.sol

pragma solidity ^0.8.0;

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * _Available since v3.4._
 */
abstract contract EIP712 {
  /* solhint-disable var-name-mixedcase */
  // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
  // invalidate the cached domain separator if the chain id changes.
  bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
  uint private immutable _CACHED_CHAIN_ID;

  bytes32 private immutable _HASHED_NAME;
  bytes32 private immutable _HASHED_VERSION;
  bytes32 private immutable _TYPE_HASH;

  /* solhint-enable var-name-mixedcase */

  /**
   * @dev Initializes the domain separator and parameter caches.
   *
   * The meaning of `name` and `version` is specified in
   * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
   *
   * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
   * - `version`: the current major version of the signing domain.
   *
   * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
   * contract upgrade].
   */
  constructor(string memory name, string memory version) {
    bytes32 hashedName = keccak256(bytes(name));
    bytes32 hashedVersion = keccak256(bytes(version));
    bytes32 typeHash = keccak256(
      'EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'
    );
    _HASHED_NAME = hashedName;
    _HASHED_VERSION = hashedVersion;
    _CACHED_CHAIN_ID = block.chainid;
    _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
    _TYPE_HASH = typeHash;
  }

  /**
   * @dev Returns the domain separator for the current chain.
   */
  function _domainSeparatorV4() internal view returns (bytes32) {
    if (block.chainid == _CACHED_CHAIN_ID) {
      return _CACHED_DOMAIN_SEPARATOR;
    } else {
      return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
    }
  }

  function _buildDomainSeparator(
    bytes32 typeHash,
    bytes32 nameHash,
    bytes32 versionHash
  ) private view returns (bytes32) {
    return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
  }

  /**
   * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
   * function returns the hash of the fully encoded EIP712 message for this domain.
   *
   * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
   *
   * ```solidity
   * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
   *     keccak256("Mail(address to,string contents)"),
   *     mailTo,
   *     keccak256(bytes(mailContents))
   * )));
   * address signer = ECDSA.recover(digest, signature);
   * ```
   */
  function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
    return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
  }
}

// File: @openzeppelin/[email protected]/token/ERC20/extensions/draft-IERC20Permit.sol

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
  /**
   * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
   * given ``owner``'s signed approval.
   *
   * IMPORTANT: The same issues {IERC20-approve} has related to transaction
   * ordering also apply here.
   *
   * Emits an {Approval} event.
   *
   * Requirements:
   *
   * - `spender` cannot be the zero address.
   * - `deadline` must be a timestamp in the future.
   * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
   * over the EIP712-formatted function arguments.
   * - the signature must use ``owner``'s current nonce (see {nonces}).
   *
   * For more information on the signature format, see the
   * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
   * section].
   */
  function permit(
    address owner,
    address spender,
    uint value,
    uint deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external;

  /**
   * @dev Returns the current nonce for `owner`. This value must be
   * included whenever a signature is generated for {permit}.
   *
   * Every successful call to {permit} increases ``owner``'s nonce by one. This
   * prevents a signature from being used multiple times.
   */
  function nonces(address owner) external view returns (uint);

  /**
   * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
   */
  // solhint-disable-next-line func-name-mixedcase
  function DOMAIN_SEPARATOR() external view returns (bytes32);
}

// File: @openzeppelin/[email protected]/utils/structs/EnumerableSet.sol

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.
 */
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 => uint) _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
    uint 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}.

      uint toDeleteIndex = valueIndex - 1;
      uint 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 (uint) {
    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, uint index) private view returns (bytes32) {
    return set._values[index];
  }

  // 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 (uint) {
    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, uint index) internal view returns (bytes32) {
    return _at(set._inner, index);
  }

  // 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(uint(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(uint(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(uint(uint160(value))));
  }

  /**
   * @dev Returns the number of values in the set. O(1).
   */
  function length(AddressSet storage set) internal view returns (uint) {
    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, uint index) internal view returns (address) {
    return address(uint160(uint(_at(set._inner, index))));
  }

  // 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, uint 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, uint 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, uint value) internal view returns (bool) {
    return _contains(set._inner, bytes32(value));
  }

  /**
   * @dev Returns the number of values on the set. O(1).
   */
  function length(UintSet storage set) internal view returns (uint) {
    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, uint index) internal view returns (uint) {
    return uint(_at(set._inner, index));
  }
}

// File: @openzeppelin/[email protected]/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/[email protected]/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/[email protected]/utils/Strings.sol

pragma solidity ^0.8.0;

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

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

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

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

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


// File: @openzeppelin/[email protected]/token/ERC20/IERC20.sol

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

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

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

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

// File: @openzeppelin/[email protected]/token/ERC20/extensions/IERC20Metadata.sol

pragma solidity ^0.8.0;

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}


// File: @openzeppelin/[email protected]/token/ERC20/ERC20.sol

pragma solidity ^0.8.0;

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

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

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

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

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

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

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

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

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        unchecked {
            _approve(sender, _msgSender(), currentAllowance - amount);
        }

        return true;
    }

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

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

        return true;
    }

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

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, amount);
    }

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

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

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

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

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

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

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

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

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

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


// File: @openzeppelin/[email protected]/access/AccessControl.sol

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
  function hasRole(bytes32 role, address account) external view returns (bool);

  function getRoleAdmin(bytes32 role) external view returns (bytes32);

  function grantRole(bytes32 role, address account) external;

  function revokeRole(bytes32 role, address account) external;

  function renounceRole(bytes32 role, address account) external;
}

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
  struct RoleData {
    mapping(address => bool) members;
    bytes32 adminRole;
  }

  mapping(bytes32 => RoleData) private _roles;

  bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

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

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

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

  /**
   * @dev Modifier that checks that an account has a specific role. Reverts
   * with a standardized message including the required role.
   *
   * The format of the revert reason is given by the following regular expression:
   *
   *  /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/
   *
   * _Available since v4.1._
   */
  modifier onlyRole(bytes32 role) {
    _checkRole(role, _msgSender());
    _;
  }

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

  /**
   * @dev Returns `true` if `account` has been granted `role`.
   */
  function hasRole(bytes32 role, address account) public view override returns (bool) {
    return _roles[role].members[account];
  }

  /**
   * @dev Revert with a standard message if `account` is missing `role`.
   *
   * The format of the revert reason is given by the following regular expression:
   *
   *  /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/
   */
  function _checkRole(bytes32 role, address account) internal view {
    if (!hasRole(role, account)) {
      revert(
        string(
          abi.encodePacked(
            'AccessControl: account ',
            Strings.toHexString(uint160(account), 20),
            ' is missing role ',
            Strings.toHexString(uint(role), 32)
          )
        )
      );
    }
  }

  /**
   * @dev Returns the admin role that controls `role`. See {grantRole} and
   * {revokeRole}.
   *
   * To change a role's admin, use {_setRoleAdmin}.
   */
  function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
    return _roles[role].adminRole;
  }

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

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

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

    _revokeRole(role, account);
  }

  /**
   * @dev Grants `role` to `account`.
   *
   * If `account` had not been already granted `role`, emits a {RoleGranted}
   * event. Note that unlike {grantRole}, this function doesn't perform any
   * checks on the calling account.
   *
   * [WARNING]
   * ====
   * This function should only be called from the constructor when setting
   * up the initial roles for the system.
   *
   * Using this function in any other way is effectively circumventing the admin
   * system imposed by {AccessControl}.
   * ====
   */
  function _setupRole(bytes32 role, address account) internal virtual {
    _grantRole(role, account);
  }

  /**
   * @dev Sets `adminRole` as ``role``'s admin role.
   *
   * Emits a {RoleAdminChanged} event.
   */
  function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
    emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);
    _roles[role].adminRole = adminRole;
  }

  function _grantRole(bytes32 role, address account) private {
    if (!hasRole(role, account)) {
      _roles[role].members[account] = true;
      emit RoleGranted(role, account, _msgSender());
    }
  }

  function _revokeRole(bytes32 role, address account) private {
    if (hasRole(role, account)) {
      _roles[role].members[account] = false;
      emit RoleRevoked(role, account, _msgSender());
    }
  }
}

// File: @openzeppelin/[email protected]/access/AccessControlEnumerable.sol

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
 */
interface IAccessControlEnumerable {
    function getRoleMember(bytes32 role, uint256 index) external view returns (address);

    function getRoleMemberCount(bytes32 role) external view returns (uint256);
}

/**
 * @dev Extension of {AccessControl} that allows enumerating the members of each role.
 */
abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {
    using EnumerableSet for EnumerableSet.AddressSet;

    mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;

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

    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) public view override returns (address) {
        return _roleMembers[role].at(index);
    }

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) public view override returns (uint256) {
        return _roleMembers[role].length();
    }

    /**
     * @dev Overload {grantRole} to track enumerable memberships
     */
    function grantRole(bytes32 role, address account) public virtual override {
        super.grantRole(role, account);
        _roleMembers[role].add(account);
    }

    /**
     * @dev Overload {revokeRole} to track enumerable memberships
     */
    function revokeRole(bytes32 role, address account) public virtual override {
        super.revokeRole(role, account);
        _roleMembers[role].remove(account);
    }

    /**
     * @dev Overload {renounceRole} to track enumerable memberships
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        super.renounceRole(role, account);
        _roleMembers[role].remove(account);
    }

    /**
     * @dev Overload {_setupRole} to track enumerable memberships
     */
    function _setupRole(bytes32 role, address account) internal virtual override {
        super._setupRole(role, account);
        _roleMembers[role].add(account);
    }
}

// File: @openzeppelin/[email protected]/security/Pausable.sol

pragma solidity ^0.8.0;

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

// File: @openzeppelin/[email protected]/token/ERC20/extensions/ERC20Pausable.sol

pragma solidity ^0.8.0;

/**
 * @dev ERC20 token with pausable token transfers, minting and burning.
 *
 * Useful for scenarios such as preventing trades until the end of an evaluation
 * period, or having an emergency switch for freezing all token transfers in the
 * event of a large bug.
 */
abstract contract ERC20Pausable is ERC20, Pausable {
    /**
     * @dev See {ERC20-_beforeTokenTransfer}.
     *
     * Requirements:
     *
     * - the contract must not be paused.
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, amount);

        require(!paused(), "ERC20Pausable: token transfer while paused");
    }
}

// File: @openzeppelin/[email protected]/token/ERC20/extensions/ERC20Burnable.sol

pragma solidity ^0.8.0;

/**
 * @dev Extension of {ERC20} that allows token holders to destroy both their own
 * tokens and those that they have an allowance for, in a way that can be
 * recognized off-chain (via event analysis).
 */
abstract contract ERC20Burnable is Context, ERC20 {
    /**
     * @dev Destroys `amount` tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 amount) public virtual {
        _burn(_msgSender(), amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, deducting from the caller's
     * allowance.
     *
     * See {ERC20-_burn} and {ERC20-allowance}.
     *
     * Requirements:
     *
     * - the caller must have allowance for ``accounts``'s tokens of at least
     * `amount`.
     */
    function burnFrom(address account, uint256 amount) public virtual {
        uint256 currentAllowance = allowance(account, _msgSender());
        require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance");
        unchecked {
            _approve(account, _msgSender(), currentAllowance - amount);
        }
        _burn(account, amount);
    }
}


// File: @openzeppelin/[email protected]/token/ERC20/extensions/draft-ERC20Permit.sol

pragma solidity ^0.8.0;

/**
 * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * _Available since v3.4._
 */
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
    using Counters for Counters.Counter;

    mapping(address => Counters.Counter) private _nonces;

    // solhint-disable-next-line var-name-mixedcase
    bytes32 private immutable _PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

    /**
     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
     *
     * It's a good idea to use the same `name` that is defined as the ERC20 token name.
     */
    constructor(string memory name) EIP712(name, "1") {}

    /**
     * @dev See {IERC20Permit-permit}.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override {
        require(block.timestamp <= deadline, "ERC20Permit: expired deadline");

        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));

        bytes32 hash = _hashTypedDataV4(structHash);

        address signer = ECDSA.recover(hash, v, r, s);
        require(signer == owner, "ERC20Permit: invalid signature");

        _approve(owner, spender, value);
    }

    /**
     * @dev See {IERC20Permit-nonces}.
     */
    function nonces(address owner) public view virtual override returns (uint256) {
        return _nonces[owner].current();
    }

    /**
     * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view override returns (bytes32) {
        return _domainSeparatorV4();
    }

    /**
     * @dev "Consume a nonce": return the current value and increment.
     *
     * _Available since v4.1._
     */
    function _useNonce(address owner) internal virtual returns (uint256 current) {
        Counters.Counter storage nonce = _nonces[owner];
        current = nonce.current();
        nonce.increment();
    }
}

// File: @openzeppelin/[email protected]/token/ERC20/presets/ERC20PresetMinterPauser.sol

pragma solidity ^0.8.0;

/**
 * @dev {ERC20} token, including:
 *
 *  - ability for holders to burn (destroy) their tokens
 *  - a minter role that allows for token minting (creation)
 *  - a pauser role that allows to stop all token transfers
 *
 * This contract uses {AccessControl} to lock permissioned functions using the
 * different roles - head to its documentation for details.
 *
 * The account that deploys the contract will be granted the minter and pauser
 * roles, as well as the default admin role, which will let it grant both minter
 * and pauser roles to other accounts.
 */
contract ERC20PresetMinterPauser is Context, AccessControlEnumerable, ERC20Burnable, ERC20Pausable {
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

    /**
     * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the
     * account that deploys the contract.
     *
     * See {ERC20-constructor}.
     */
    constructor(string memory name, string memory symbol) ERC20(name, symbol) {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());

        _setupRole(MINTER_ROLE, _msgSender());
        _setupRole(PAUSER_ROLE, _msgSender());
    }

    /**
     * @dev Creates `amount` new tokens for `to`.
     *
     * See {ERC20-_mint}.
     *
     * Requirements:
     *
     * - the caller must have the `MINTER_ROLE`.
     */
    function mint(address to, uint256 amount) public virtual {
        require(hasRole(MINTER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have minter role to mint");
        _mint(to, amount);
    }

    /**
     * @dev Pauses all token transfers.
     *
     * See {ERC20Pausable} and {Pausable-_pause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function pause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to pause");
        _pause();
    }

    /**
     * @dev Unpauses all token transfers.
     *
     * See {ERC20Pausable} and {Pausable-_unpause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function unpause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to unpause");
        _unpause();
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override(ERC20, ERC20Pausable) {
        super._beforeTokenTransfer(from, to, amount);
    }
}

// File: BetaToken.sol

pragma solidity 0.8.6;

contract BetaToken is ERC20PresetMinterPauser('Beta Token', 'BETA'), ERC20Permit('BETA') {
  function _beforeTokenTransfer(
    address from,
    address to,
    uint amount
  ) internal virtual override(ERC20, ERC20PresetMinterPauser) {
    ERC20PresetMinterPauser._beforeTokenTransfer(from, to, amount);
  }
}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"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":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101406040527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9610120523480156200003757600080fd5b50604051806040016040528060048152602001634245544160e01b81525080604051806040016040528060018152602001603160f81b8152506040518060400160405280600a8152602001692132ba30902a37b5b2b760b11b815250604051806040016040528060048152602001634245544160e01b81525081818160059080519060200190620000ca92919062000349565b508051620000e090600690602084019062000349565b50506007805460ff1916905550620000fa600033620001e4565b620001267f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633620001e4565b620001527f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33620001e4565b5050815160209283012081519183019190912060c082815260e08290524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81890181905281830197909752606081019590955260808086019390935230858301528051808603909201825293909201909252805193019290922090915261010052506200042c565b620001fb82826200022760201b62000bc91760201c565b60008281526001602090815260409091206200022291839062000bd362000237821b17901c565b505050565b62000233828262000257565b5050565b60006200024e836001600160a01b038416620002f7565b90505b92915050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1662000233576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620002b33390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000818152600183016020526040812054620003405750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000251565b50600062000251565b8280546200035790620003ef565b90600052602060002090601f0160209004810192826200037b5760008555620003c6565b82601f106200039657805160ff1916838001178555620003c6565b82800160010185558215620003c6579182015b82811115620003c6578251825591602001919060010190620003a9565b50620003d4929150620003d8565b5090565b5b80821115620003d45760008155600101620003d9565b600181811c908216806200040457607f821691505b602082108114156200042657634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e0516101005161012051611f0a6200047c6000396000610aaf01526000610f9801526000610fe701526000610fc201526000610f4601526000610f6f0152611f0a6000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c806370a082311161010f578063a457c2d7116100a2578063d539139311610071578063d5391393146103fe578063d547741f14610425578063dd62ed3e14610438578063e63ab1e91461047157600080fd5b8063a457c2d7146103b2578063a9059cbb146103c5578063ca15c873146103d8578063d505accf146103eb57600080fd5b80639010d07c116100de5780639010d07c1461036457806391d148541461038f57806395d89b41146103a2578063a217fddf146103aa57600080fd5b806370a082311461030d57806379cc6790146103365780637ecebe00146103495780638456cb591461035c57600080fd5b8063313ce567116101875780633f4ba83a116101565780633f4ba83a146102d457806340c10f19146102dc57806342966c68146102ef5780635c975abb1461030257600080fd5b8063313ce567146102975780633644e515146102a657806336568abe146102ae57806339509351146102c157600080fd5b806318160ddd116101c357806318160ddd1461023a57806323b872dd1461024c578063248a9ca31461025f5780632f2ff15d1461028257600080fd5b806301ffc9a7146101ea57806306fdde0314610212578063095ea7b314610227575b600080fd5b6101fd6101f8366004611ce4565b610498565b60405190151581526020015b60405180910390f35b61021a6104c3565b6040516102099190611d83565b6101fd610235366004611c5c565b610555565b6004545b604051908152602001610209565b6101fd61025a366004611bad565b61056b565b61023e61026d366004611c86565b60009081526020819052604090206001015490565b610295610290366004611c9f565b61061a565b005b60405160128152602001610209565b61023e610641565b6102956102bc366004611c9f565b610650565b6101fd6102cf366004611c5c565b610672565b6102956106ae565b6102956102ea366004611c5c565b610754565b6102956102fd366004611c86565b6107f7565b60075460ff166101fd565b61023e61031b366004611b5f565b6001600160a01b031660009081526002602052604090205490565b610295610344366004611c5c565b610804565b61023e610357366004611b5f565b610885565b6102956108a3565b610377610372366004611cc2565b610947565b6040516001600160a01b039091168152602001610209565b6101fd61039d366004611c9f565b610966565b61021a61098f565b61023e600081565b6101fd6103c0366004611c5c565b61099e565b6101fd6103d3366004611c5c565b610a37565b61023e6103e6366004611c86565b610a44565b6102956103f9366004611be9565b610a5b565b61023e7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b610295610433366004611c9f565b610bbf565b61023e610446366004611b7a565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205490565b61023e7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b60006001600160e01b03198216635a05180f60e01b14806104bd57506104bd82610be8565b92915050565b6060600580546104d290611e47565b80601f01602080910402602001604051908101604052809291908181526020018280546104fe90611e47565b801561054b5780601f106105205761010080835404028352916020019161054b565b820191906000526020600020905b81548152906001019060200180831161052e57829003601f168201915b5050505050905090565b6000610562338484610c1d565b50600192915050565b6000610578848484610d41565b6001600160a01b0384166000908152600360209081526040808320338452909152902054828110156106025760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b61060f8533858403610c1d565b506001949350505050565b6106248282610f1c565b600082815260016020526040902061063c9082610bd3565b505050565b600061064b610f42565b905090565b61065a8282611035565b600082815260016020526040902061063c90826110af565b3360008181526003602090815260408083206001600160a01b038716845290915281205490916105629185906106a9908690611db6565b610c1d565b6106d87f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33610966565b61074a5760405162461bcd60e51b815260206004820152603960248201527f45524332305072657365744d696e7465725061757365723a206d75737420686160448201527f76652070617573657220726f6c6520746f20756e70617573650000000000000060648201526084016105f9565b6107526110c4565b565b61077e7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633610966565b6107e95760405162461bcd60e51b815260206004820152603660248201527f45524332305072657365744d696e7465725061757365723a206d7573742068616044820152751d99481b5a5b9d195c881c9bdb19481d1bc81b5a5b9d60521b60648201526084016105f9565b6107f38282611157565b5050565b6108013382611242565b50565b60006108108333610446565b90508181101561086e5760405162461bcd60e51b8152602060048201526024808201527f45524332303a206275726e20616d6f756e74206578636565647320616c6c6f77604482015263616e636560e01b60648201526084016105f9565b61087b8333848403610c1d565b61063c8383611242565b6001600160a01b0381166000908152600860205260408120546104bd565b6108cd7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33610966565b61093f5760405162461bcd60e51b815260206004820152603760248201527f45524332305072657365744d696e7465725061757365723a206d75737420686160448201527f76652070617573657220726f6c6520746f20706175736500000000000000000060648201526084016105f9565b61075261139c565b600082815260016020526040812061095f9083611417565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6060600680546104d290611e47565b3360009081526003602090815260408083206001600160a01b038616845290915281205482811015610a205760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016105f9565b610a2d3385858403610c1d565b5060019392505050565b6000610562338484610d41565b60008181526001602052604081206104bd90611423565b83421115610aab5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e6500000060448201526064016105f9565b60007f0000000000000000000000000000000000000000000000000000000000000000888888610ada8c61142d565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610b3582611455565b90506000610b45828787876114a3565b9050896001600160a01b0316816001600160a01b031614610ba85760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e6174757265000060448201526064016105f9565b610bb38a8a8a610c1d565b50505050505050505050565b61065a828261164c565b6107f38282611672565b600061095f836001600160a01b0384166116f6565b60006001600160e01b03198216637965db0b60e01b14806104bd57506301ffc9a760e01b6001600160e01b03198316146104bd565b6001600160a01b038316610c7f5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016105f9565b6001600160a01b038216610ce05760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016105f9565b6001600160a01b0383811660008181526003602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b038316610da55760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016105f9565b6001600160a01b038216610e075760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016105f9565b610e12838383611745565b6001600160a01b03831660009081526002602052604090205481811015610e8a5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016105f9565b6001600160a01b03808516600090815260026020526040808220858503905591851681529081208054849290610ec1908490611db6565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610f0d91815260200190565b60405180910390a35b50505050565b600082815260208190526040902060010154610f388133611750565b61063c8383611672565b60007f0000000000000000000000000000000000000000000000000000000000000000461415610f9157507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6001600160a01b03811633146110a55760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084016105f9565b6107f382826117b4565b600061095f836001600160a01b038416611819565b60075460ff1661110d5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016105f9565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0382166111ad5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016105f9565b6111b960008383611745565b80600460008282546111cb9190611db6565b90915550506001600160a01b038216600090815260026020526040812080548392906111f8908490611db6565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b0382166112a25760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016105f9565b6112ae82600083611745565b6001600160a01b038216600090815260026020526040902054818110156113225760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016105f9565b6001600160a01b0383166000908152600260205260408120838303905560048054849290611351908490611ded565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b60075460ff16156113e25760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016105f9565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861113a3390565b600061095f838361190c565b60006104bd825490565b6001600160a01b03811660009081526008602052604090208054600181018255905b50919050565b60006104bd611462610f42565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156115205760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016105f9565b8360ff16601b148061153557508360ff16601c145b61158c5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016105f9565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa1580156115e0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166116435760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016105f9565b95945050505050565b6000828152602081905260409020600101546116688133611750565b61063c83836117b4565b61167c8282610966565b6107f3576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556116b23390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600081815260018301602052604081205461173d575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556104bd565b5060006104bd565b61063c838383611936565b61175a8282610966565b6107f357611772816001600160a01b03166014611941565b61177d836020611941565b60405160200161178e929190611d0e565b60408051601f198184030181529082905262461bcd60e51b82526105f991600401611d83565b6117be8282610966565b156107f3576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000818152600183016020526040812054801561190257600061183d600183611ded565b855490915060009061185190600190611ded565b90508181146118b657600086600001828154811061187157611871611ea8565b906000526020600020015490508087600001848154811061189457611894611ea8565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806118c7576118c7611e92565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506104bd565b60009150506104bd565b600082600001828154811061192357611923611ea8565b9060005260206000200154905092915050565b61063c838383611add565b60606000611950836002611dce565b61195b906002611db6565b67ffffffffffffffff81111561197357611973611ebe565b6040519080825280601f01601f19166020018201604052801561199d576020820181803683370190505b509050600360fc1b816000815181106119b8576119b8611ea8565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106119e7576119e7611ea8565b60200101906001600160f81b031916908160001a9053506000611a0b846002611dce565b611a16906001611db6565b90505b6001811115611a8e576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611a4a57611a4a611ea8565b1a60f81b828281518110611a6057611a60611ea8565b60200101906001600160f81b031916908160001a90535060049490941c93611a8781611e30565b9050611a19565b50831561095f5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016105f9565b60075460ff161561063c5760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e736665722077686044820152691a5b19481c185d5cd95960b21b60648201526084016105f9565b80356001600160a01b0381168114611b5a57600080fd5b919050565b600060208284031215611b7157600080fd5b61095f82611b43565b60008060408385031215611b8d57600080fd5b611b9683611b43565b9150611ba460208401611b43565b90509250929050565b600080600060608486031215611bc257600080fd5b611bcb84611b43565b9250611bd960208501611b43565b9150604084013590509250925092565b600080600080600080600060e0888a031215611c0457600080fd5b611c0d88611b43565b9650611c1b60208901611b43565b95506040880135945060608801359350608088013560ff81168114611c3f57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611c6f57600080fd5b611c7883611b43565b946020939093013593505050565b600060208284031215611c9857600080fd5b5035919050565b60008060408385031215611cb257600080fd5b82359150611ba460208401611b43565b60008060408385031215611cd557600080fd5b50508035926020909101359150565b600060208284031215611cf657600080fd5b81356001600160e01b03198116811461095f57600080fd5b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611d46816017850160208801611e04565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351611d77816028840160208801611e04565b01602801949350505050565b6020815260008251806020840152611da2816040850160208701611e04565b601f01601f19169190910160400192915050565b60008219821115611dc957611dc9611e7c565b500190565b6000816000190483118215151615611de857611de8611e7c565b500290565b600082821015611dff57611dff611e7c565b500390565b60005b83811015611e1f578181015183820152602001611e07565b83811115610f165750506000910152565b600081611e3f57611e3f611e7c565b506000190190565b600181811c90821680611e5b57607f821691505b6020821081141561144f57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220a2d4c1d6ed02f2295f2da9e5b8aa1e158ec0e201c1086d52d1e9dd1322f0f04664736f6c63430008060033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101e55760003560e01c806370a082311161010f578063a457c2d7116100a2578063d539139311610071578063d5391393146103fe578063d547741f14610425578063dd62ed3e14610438578063e63ab1e91461047157600080fd5b8063a457c2d7146103b2578063a9059cbb146103c5578063ca15c873146103d8578063d505accf146103eb57600080fd5b80639010d07c116100de5780639010d07c1461036457806391d148541461038f57806395d89b41146103a2578063a217fddf146103aa57600080fd5b806370a082311461030d57806379cc6790146103365780637ecebe00146103495780638456cb591461035c57600080fd5b8063313ce567116101875780633f4ba83a116101565780633f4ba83a146102d457806340c10f19146102dc57806342966c68146102ef5780635c975abb1461030257600080fd5b8063313ce567146102975780633644e515146102a657806336568abe146102ae57806339509351146102c157600080fd5b806318160ddd116101c357806318160ddd1461023a57806323b872dd1461024c578063248a9ca31461025f5780632f2ff15d1461028257600080fd5b806301ffc9a7146101ea57806306fdde0314610212578063095ea7b314610227575b600080fd5b6101fd6101f8366004611ce4565b610498565b60405190151581526020015b60405180910390f35b61021a6104c3565b6040516102099190611d83565b6101fd610235366004611c5c565b610555565b6004545b604051908152602001610209565b6101fd61025a366004611bad565b61056b565b61023e61026d366004611c86565b60009081526020819052604090206001015490565b610295610290366004611c9f565b61061a565b005b60405160128152602001610209565b61023e610641565b6102956102bc366004611c9f565b610650565b6101fd6102cf366004611c5c565b610672565b6102956106ae565b6102956102ea366004611c5c565b610754565b6102956102fd366004611c86565b6107f7565b60075460ff166101fd565b61023e61031b366004611b5f565b6001600160a01b031660009081526002602052604090205490565b610295610344366004611c5c565b610804565b61023e610357366004611b5f565b610885565b6102956108a3565b610377610372366004611cc2565b610947565b6040516001600160a01b039091168152602001610209565b6101fd61039d366004611c9f565b610966565b61021a61098f565b61023e600081565b6101fd6103c0366004611c5c565b61099e565b6101fd6103d3366004611c5c565b610a37565b61023e6103e6366004611c86565b610a44565b6102956103f9366004611be9565b610a5b565b61023e7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b610295610433366004611c9f565b610bbf565b61023e610446366004611b7a565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205490565b61023e7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b60006001600160e01b03198216635a05180f60e01b14806104bd57506104bd82610be8565b92915050565b6060600580546104d290611e47565b80601f01602080910402602001604051908101604052809291908181526020018280546104fe90611e47565b801561054b5780601f106105205761010080835404028352916020019161054b565b820191906000526020600020905b81548152906001019060200180831161052e57829003601f168201915b5050505050905090565b6000610562338484610c1d565b50600192915050565b6000610578848484610d41565b6001600160a01b0384166000908152600360209081526040808320338452909152902054828110156106025760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b61060f8533858403610c1d565b506001949350505050565b6106248282610f1c565b600082815260016020526040902061063c9082610bd3565b505050565b600061064b610f42565b905090565b61065a8282611035565b600082815260016020526040902061063c90826110af565b3360008181526003602090815260408083206001600160a01b038716845290915281205490916105629185906106a9908690611db6565b610c1d565b6106d87f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33610966565b61074a5760405162461bcd60e51b815260206004820152603960248201527f45524332305072657365744d696e7465725061757365723a206d75737420686160448201527f76652070617573657220726f6c6520746f20756e70617573650000000000000060648201526084016105f9565b6107526110c4565b565b61077e7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633610966565b6107e95760405162461bcd60e51b815260206004820152603660248201527f45524332305072657365744d696e7465725061757365723a206d7573742068616044820152751d99481b5a5b9d195c881c9bdb19481d1bc81b5a5b9d60521b60648201526084016105f9565b6107f38282611157565b5050565b6108013382611242565b50565b60006108108333610446565b90508181101561086e5760405162461bcd60e51b8152602060048201526024808201527f45524332303a206275726e20616d6f756e74206578636565647320616c6c6f77604482015263616e636560e01b60648201526084016105f9565b61087b8333848403610c1d565b61063c8383611242565b6001600160a01b0381166000908152600860205260408120546104bd565b6108cd7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33610966565b61093f5760405162461bcd60e51b815260206004820152603760248201527f45524332305072657365744d696e7465725061757365723a206d75737420686160448201527f76652070617573657220726f6c6520746f20706175736500000000000000000060648201526084016105f9565b61075261139c565b600082815260016020526040812061095f9083611417565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6060600680546104d290611e47565b3360009081526003602090815260408083206001600160a01b038616845290915281205482811015610a205760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016105f9565b610a2d3385858403610c1d565b5060019392505050565b6000610562338484610d41565b60008181526001602052604081206104bd90611423565b83421115610aab5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e6500000060448201526064016105f9565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610ada8c61142d565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610b3582611455565b90506000610b45828787876114a3565b9050896001600160a01b0316816001600160a01b031614610ba85760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e6174757265000060448201526064016105f9565b610bb38a8a8a610c1d565b50505050505050505050565b61065a828261164c565b6107f38282611672565b600061095f836001600160a01b0384166116f6565b60006001600160e01b03198216637965db0b60e01b14806104bd57506301ffc9a760e01b6001600160e01b03198316146104bd565b6001600160a01b038316610c7f5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016105f9565b6001600160a01b038216610ce05760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016105f9565b6001600160a01b0383811660008181526003602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b038316610da55760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016105f9565b6001600160a01b038216610e075760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016105f9565b610e12838383611745565b6001600160a01b03831660009081526002602052604090205481811015610e8a5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016105f9565b6001600160a01b03808516600090815260026020526040808220858503905591851681529081208054849290610ec1908490611db6565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610f0d91815260200190565b60405180910390a35b50505050565b600082815260208190526040902060010154610f388133611750565b61063c8383611672565b60007f0000000000000000000000000000000000000000000000000000000000000001461415610f9157507fc5c378912a6a73eff51677e60d12cb059e779643d913403e3727aaf60a37a06f90565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f0c97b5255f0de5334f50bb470d8db2f56626f0853111cf4e5cf766ee733df095828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6001600160a01b03811633146110a55760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084016105f9565b6107f382826117b4565b600061095f836001600160a01b038416611819565b60075460ff1661110d5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016105f9565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0382166111ad5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016105f9565b6111b960008383611745565b80600460008282546111cb9190611db6565b90915550506001600160a01b038216600090815260026020526040812080548392906111f8908490611db6565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b0382166112a25760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016105f9565b6112ae82600083611745565b6001600160a01b038216600090815260026020526040902054818110156113225760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016105f9565b6001600160a01b0383166000908152600260205260408120838303905560048054849290611351908490611ded565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b60075460ff16156113e25760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016105f9565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861113a3390565b600061095f838361190c565b60006104bd825490565b6001600160a01b03811660009081526008602052604090208054600181018255905b50919050565b60006104bd611462610f42565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156115205760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016105f9565b8360ff16601b148061153557508360ff16601c145b61158c5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016105f9565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa1580156115e0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166116435760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016105f9565b95945050505050565b6000828152602081905260409020600101546116688133611750565b61063c83836117b4565b61167c8282610966565b6107f3576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556116b23390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600081815260018301602052604081205461173d575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556104bd565b5060006104bd565b61063c838383611936565b61175a8282610966565b6107f357611772816001600160a01b03166014611941565b61177d836020611941565b60405160200161178e929190611d0e565b60408051601f198184030181529082905262461bcd60e51b82526105f991600401611d83565b6117be8282610966565b156107f3576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000818152600183016020526040812054801561190257600061183d600183611ded565b855490915060009061185190600190611ded565b90508181146118b657600086600001828154811061187157611871611ea8565b906000526020600020015490508087600001848154811061189457611894611ea8565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806118c7576118c7611e92565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506104bd565b60009150506104bd565b600082600001828154811061192357611923611ea8565b9060005260206000200154905092915050565b61063c838383611add565b60606000611950836002611dce565b61195b906002611db6565b67ffffffffffffffff81111561197357611973611ebe565b6040519080825280601f01601f19166020018201604052801561199d576020820181803683370190505b509050600360fc1b816000815181106119b8576119b8611ea8565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106119e7576119e7611ea8565b60200101906001600160f81b031916908160001a9053506000611a0b846002611dce565b611a16906001611db6565b90505b6001811115611a8e576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611a4a57611a4a611ea8565b1a60f81b828281518110611a6057611a60611ea8565b60200101906001600160f81b031916908160001a90535060049490941c93611a8781611e30565b9050611a19565b50831561095f5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016105f9565b60075460ff161561063c5760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e736665722077686044820152691a5b19481c185d5cd95960b21b60648201526084016105f9565b80356001600160a01b0381168114611b5a57600080fd5b919050565b600060208284031215611b7157600080fd5b61095f82611b43565b60008060408385031215611b8d57600080fd5b611b9683611b43565b9150611ba460208401611b43565b90509250929050565b600080600060608486031215611bc257600080fd5b611bcb84611b43565b9250611bd960208501611b43565b9150604084013590509250925092565b600080600080600080600060e0888a031215611c0457600080fd5b611c0d88611b43565b9650611c1b60208901611b43565b95506040880135945060608801359350608088013560ff81168114611c3f57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611c6f57600080fd5b611c7883611b43565b946020939093013593505050565b600060208284031215611c9857600080fd5b5035919050565b60008060408385031215611cb257600080fd5b82359150611ba460208401611b43565b60008060408385031215611cd557600080fd5b50508035926020909101359150565b600060208284031215611cf657600080fd5b81356001600160e01b03198116811461095f57600080fd5b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611d46816017850160208801611e04565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351611d77816028840160208801611e04565b01602801949350505050565b6020815260008251806020840152611da2816040850160208701611e04565b601f01601f19169190910160400192915050565b60008219821115611dc957611dc9611e7c565b500190565b6000816000190483118215151615611de857611de8611e7c565b500290565b600082821015611dff57611dff611e7c565b500390565b60005b83811015611e1f578181015183820152602001611e07565b83811115610f165750506000910152565b600081611e3f57611e3f611e7c565b506000190190565b600181811c90821680611e5b57607f821691505b6020821081141561144f57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220a2d4c1d6ed02f2295f2da9e5b8aa1e158ec0e201c1086d52d1e9dd1322f0f04664736f6c63430008060033

Deployed Bytecode Sourcemap

63627:319:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51254:214;;;;;;:::i;:::-;;:::i;:::-;;;4672:14:1;;4665:22;4647:41;;4635:2;4620:18;51254:214:0;;;;;;;;32223:100;;;:::i;:::-;;;;;;;:::i;34390:169::-;;;;;;:::i;:::-;;:::i;33343:108::-;33431:12;;33343:108;;;4845:25:1;;;4833:2;4818:18;33343:108:0;4800:76:1;35041:492:0;;;;;;:::i;:::-;;:::i;47456:117::-;;;;;;:::i;:::-;47522:7;47545:12;;;;;;;;;;:22;;;;47456:117;52612:165;;;;;;:::i;:::-;;:::i;:::-;;33185:93;;;33268:2;16527:36:1;;16515:2;16500:18;33185:93:0;16482:87:1;60327:115:0;;;:::i;53135:174::-;;;;;;:::i;:::-;;:::i;35942:215::-;;;;;;:::i;:::-;;:::i;63165:178::-;;;:::i;62356:205::-;;;;;;:::i;:::-;;:::i;57197:91::-;;;;;;:::i;:::-;;:::i;54652:86::-;54723:7;;;;54652:86;;33514:127;;;;;;:::i;:::-;-1:-1:-1;;;;;33615:18:0;33588:7;33615:18;;;:9;:18;;;;;;;33514:127;57607:368;;;;;;:::i;:::-;;:::i;60069:128::-;;;;;;:::i;:::-;;:::i;62775:172::-;;;:::i;52067:145::-;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;4463:32:1;;;4445:51;;4433:2;4418:18;52067:145:0;4400:102:1;46486:133:0;;;;;;:::i;:::-;;:::i;32442:104::-;;;:::i;44546:49::-;;44591:4;44546:49;;36660:413;;;;;;:::i;:::-;;:::i;33854:175::-;;;;;;:::i;:::-;;:::i;52386:134::-;;;;;;:::i;:::-;;:::i;59358:645::-;;;;;;:::i;:::-;;:::i;61598:62::-;;61636:24;61598:62;;52870:170;;;;;;:::i;:::-;;:::i;34092:151::-;;;;;;:::i;:::-;-1:-1:-1;;;;;34208:18:0;;;34181:7;34208:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;34092:151;61667:62;;61705:24;61667:62;;51254:214;51339:4;-1:-1:-1;;;;;;51363:57:0;;-1:-1:-1;;;51363:57:0;;:97;;;51424:36;51448:11;51424:23;:36::i;:::-;51356:104;51254:214;-1:-1:-1;;51254:214:0:o;32223:100::-;32277:13;32310:5;32303:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32223:100;:::o;34390:169::-;34473:4;34490:39;706:10;34513:7;34522:6;34490:8;:39::i;:::-;-1:-1:-1;34547:4:0;34390:169;;;;:::o;35041:492::-;35181:4;35198:36;35208:6;35216:9;35227:6;35198:9;:36::i;:::-;-1:-1:-1;;;;;35274:19:0;;35247:24;35274:19;;;:11;:19;;;;;;;;706:10;35274:33;;;;;;;;35326:26;;;;35318:79;;;;-1:-1:-1;;;35318:79:0;;11938:2:1;35318:79:0;;;11920:21:1;11977:2;11957:18;;;11950:30;12016:34;11996:18;;;11989:62;-1:-1:-1;;;12067:18:1;;;12060:38;12115:19;;35318:79:0;;;;;;;;;35433:57;35442:6;706:10;35483:6;35464:16;:25;35433:8;:57::i;:::-;-1:-1:-1;35521:4:0;;35041:492;-1:-1:-1;;;;35041:492:0:o;52612:165::-;52697:30;52713:4;52719:7;52697:15;:30::i;:::-;52738:18;;;;:12;:18;;;;;:31;;52761:7;52738:22;:31::i;:::-;;52612:165;;:::o;60327:115::-;60387:7;60414:20;:18;:20::i;:::-;60407:27;;60327:115;:::o;53135:174::-;53223:33;53242:4;53248:7;53223:18;:33::i;:::-;53267:18;;;;:12;:18;;;;;:34;;53293:7;53267:25;:34::i;35942:215::-;706:10;36030:4;36079:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;36079:34:0;;;;;;;;;;36030:4;;36047:80;;36070:7;;36079:47;;36116:10;;36079:47;:::i;:::-;36047:8;:80::i;63165:178::-;63218:34;61705:24;706:10;46486:133;:::i;63218:34::-;63210:104;;;;-1:-1:-1;;;63210:104:0;;8834:2:1;63210:104:0;;;8816:21:1;8873:2;8853:18;;;8846:30;8912:34;8892:18;;;8885:62;8983:27;8963:18;;;8956:55;9028:19;;63210:104:0;8806:247:1;63210:104:0;63325:10;:8;:10::i;:::-;63165:178::o;62356:205::-;62432:34;61636:24;706:10;46486:133;:::i;62432:34::-;62424:101;;;;-1:-1:-1;;;62424:101:0;;12347:2:1;62424:101:0;;;12329:21:1;12386:2;12366:18;;;12359:30;12425:34;12405:18;;;12398:62;-1:-1:-1;;;12476:18:1;;;12469:52;12538:19;;62424:101:0;12319:244:1;62424:101:0;62536:17;62542:2;62546:6;62536:5;:17::i;:::-;62356:205;;:::o;57197:91::-;57253:27;706:10;57273:6;57253:5;:27::i;:::-;57197:91;:::o;57607:368::-;57684:24;57711:32;57721:7;706:10;34092:151;:::i;57711:32::-;57684:59;;57782:6;57762:16;:26;;57754:75;;;;-1:-1:-1;;;57754:75:0;;12770:2:1;57754:75:0;;;12752:21:1;12809:2;12789:18;;;12782:30;12848:34;12828:18;;;12821:62;-1:-1:-1;;;12899:18:1;;;12892:34;12943:19;;57754:75:0;12742:226:1;57754:75:0;57865:58;57874:7;706:10;57916:6;57897:16;:25;57865:8;:58::i;:::-;57945:22;57951:7;57960:6;57945:5;:22::i;60069:128::-;-1:-1:-1;;;;;60165:14:0;;60138:7;60165:14;;;:7;:14;;;;;1719;60165:24;1634:105;62775:172;62826:34;61705:24;706:10;46486:133;:::i;62826:34::-;62818:102;;;;-1:-1:-1;;;62818:102:0;;14388:2:1;62818:102:0;;;14370:21:1;14427:2;14407:18;;;14400:30;14466:34;14446:18;;;14439:62;14537:25;14517:18;;;14510:53;14580:19;;62818:102:0;14360:245:1;62818:102:0;62931:8;:6;:8::i;52067:145::-;52149:7;52176:18;;;:12;:18;;;;;:28;;52198:5;52176:21;:28::i;:::-;52169:35;52067:145;-1:-1:-1;;;52067:145:0:o;46486:133::-;46564:4;46584:12;;;;;;;;;;;-1:-1:-1;;;;;46584:29:0;;;;;;;;;;;;;;;46486:133::o;32442:104::-;32498:13;32531:7;32524:14;;;;;:::i;36660:413::-;706:10;36753:4;36797:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;36797:34:0;;;;;;;;;;36850:35;;;;36842:85;;;;-1:-1:-1;;;36842:85:0;;14812:2:1;36842:85:0;;;14794:21:1;14851:2;14831:18;;;14824:30;14890:34;14870:18;;;14863:62;-1:-1:-1;;;14941:18:1;;;14934:35;14986:19;;36842:85:0;14784:227:1;36842:85:0;36963:67;706:10;36986:7;37014:15;36995:16;:34;36963:8;:67::i;:::-;-1:-1:-1;37061:4:0;;36660:413;-1:-1:-1;;;36660:413:0:o;33854:175::-;33940:4;33957:42;706:10;33981:9;33992:6;33957:9;:42::i;52386:134::-;52458:7;52485:18;;;:12;:18;;;;;:27;;:25;:27::i;59358:645::-;59602:8;59583:15;:27;;59575:69;;;;-1:-1:-1;;;59575:69:0;;9663:2:1;59575:69:0;;;9645:21:1;9702:2;9682:18;;;9675:30;9741:31;9721:18;;;9714:59;9790:18;;59575:69:0;9635:179:1;59575:69:0;59657:18;59699:16;59717:5;59724:7;59733:5;59740:16;59750:5;59740:9;:16::i;:::-;59688:79;;;;;;5168:25:1;;;;-1:-1:-1;;;;;5267:15:1;;;5247:18;;;5240:43;5319:15;;;;5299:18;;;5292:43;5351:18;;;5344:34;5394:19;;;5387:35;5438:19;;;5431:35;;;5140:19;;59688:79:0;;;;;;;;;;;;59678:90;;;;;;59657:111;;59781:12;59796:28;59813:10;59796:16;:28::i;:::-;59781:43;;59837:14;59854:28;59868:4;59874:1;59877;59880;59854:13;:28::i;:::-;59837:45;;59911:5;-1:-1:-1;;;;;59901:15:0;:6;-1:-1:-1;;;;;59901:15:0;;59893:58;;;;-1:-1:-1;;;59893:58:0;;11579:2:1;59893:58:0;;;11561:21:1;11618:2;11598:18;;;11591:30;11657:32;11637:18;;;11630:60;11707:18;;59893:58:0;11551:180:1;59893:58:0;59964:31;59973:5;59980:7;59989:5;59964:8;:31::i;:::-;59564:439;;;59358:645;;;;;;;:::o;52870:170::-;52956:31;52973:4;52979:7;52956:16;:31::i;49602:106::-;49677:25;49688:4;49694:7;49677:10;:25::i;20195:143::-;20265:4;20285:47;20290:3;-1:-1:-1;;;;;20310:20:0;;20285:4;:47::i;46204:198::-;46289:4;-1:-1:-1;;;;;;46309:47:0;;-1:-1:-1;;;46309:47:0;;:87;;-1:-1:-1;;;;;;;;;;24772:40:0;;;46360:36;24667:151;40344:380;-1:-1:-1;;;;;40480:19:0;;40472:68;;;;-1:-1:-1;;;40472:68:0;;13983:2:1;40472:68:0;;;13965:21:1;14022:2;14002:18;;;13995:30;14061:34;14041:18;;;14034:62;-1:-1:-1;;;14112:18:1;;;14105:34;14156:19;;40472:68:0;13955:226:1;40472:68:0;-1:-1:-1;;;;;40559:21:0;;40551:68;;;;-1:-1:-1;;;40551:68:0;;9260:2:1;40551:68:0;;;9242:21:1;9299:2;9279:18;;;9272:30;9338:34;9318:18;;;9311:62;-1:-1:-1;;;9389:18:1;;;9382:32;9431:19;;40551:68:0;9232:224:1;40551:68:0;-1:-1:-1;;;;;40632:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;40684:32;;4845:25:1;;;40684:32:0;;4818:18:1;40684:32:0;;;;;;;40344:380;;;:::o;37563:733::-;-1:-1:-1;;;;;37703:20:0;;37695:70;;;;-1:-1:-1;;;37695:70:0;;13577:2:1;37695:70:0;;;13559:21:1;13616:2;13596:18;;;13589:30;13655:34;13635:18;;;13628:62;-1:-1:-1;;;13706:18:1;;;13699:35;13751:19;;37695:70:0;13549:227:1;37695:70:0;-1:-1:-1;;;;;37784:23:0;;37776:71;;;;-1:-1:-1;;;37776:71:0;;7678:2:1;37776:71:0;;;7660:21:1;7717:2;7697:18;;;7690:30;7756:34;7736:18;;;7729:62;-1:-1:-1;;;7807:18:1;;;7800:33;7850:19;;37776:71:0;7650:225:1;37776:71:0;37860:47;37881:6;37889:9;37900:6;37860:20;:47::i;:::-;-1:-1:-1;;;;;37944:17:0;;37920:21;37944:17;;;:9;:17;;;;;;37980:23;;;;37972:74;;;;-1:-1:-1;;;37972:74:0;;10021:2:1;37972:74:0;;;10003:21:1;10060:2;10040:18;;;10033:30;10099:34;10079:18;;;10072:62;-1:-1:-1;;;10150:18:1;;;10143:36;10196:19;;37972:74:0;9993:228:1;37972:74:0;-1:-1:-1;;;;;38082:17:0;;;;;;;:9;:17;;;;;;38102:22;;;38082:42;;38146:20;;;;;;;;:30;;38118:6;;38082:17;38146:30;;38118:6;;38146:30;:::i;:::-;;;;;;;;38211:9;-1:-1:-1;;;;;38194:35:0;38203:6;-1:-1:-1;;;;;38194:35:0;;38222:6;38194:35;;;;4845:25:1;;4833:2;4818:18;;4800:76;38194:35:0;;;;;;;;38242:46;37684:612;37563:733;;;:::o;47813:164::-;47522:7;47545:12;;;;;;;;;;:22;;;46096:30;46107:4;706:10;46096;:30::i;:::-;47946:25:::1;47957:4;47963:7;47946:10;:25::i;10742:255::-:0;10795:7;10832:16;10815:13;:33;10811:181;;;-1:-1:-1;10866:24:0;;10742:255::o;10811:181::-;-1:-1:-1;11166:73:0;;;10942:10;11166:73;;;;5736:25:1;;;;10954:12:0;5777:18:1;;;5770:34;10968:15:0;5820:18:1;;;5813:34;11210:13:0;5863:18:1;;;5856:34;11233:4:0;5906:19:1;;;;5899:61;;;;11166:73:0;;;;;;;;;;5708:19:1;;;;11166:73:0;;;11156:84;;;;;;60327:115::o;48845:208::-;-1:-1:-1;;;;;48937:23:0;;706:10;48937:23;48929:83;;;;-1:-1:-1;;;48929:83:0;;15218:2:1;48929:83:0;;;15200:21:1;15257:2;15237:18;;;15230:30;15296:34;15276:18;;;15269:62;-1:-1:-1;;;15347:18:1;;;15340:45;15402:19;;48929:83:0;15190:237:1;48929:83:0;49021:26;49033:4;49039:7;49021:11;:26::i;20500:149::-;20573:4;20593:50;20601:3;-1:-1:-1;;;;;20621:20:0;;20593:7;:50::i;55711:120::-;54723:7;;;;55247:41;;;;-1:-1:-1;;;55247:41:0;;8082:2:1;55247:41:0;;;8064:21:1;8121:2;8101:18;;;8094:30;-1:-1:-1;;;8140:18:1;;;8133:50;8200:18;;55247:41:0;8054:170:1;55247:41:0;55770:7:::1;:15:::0;;-1:-1:-1;;55770:15:0::1;::::0;;55801:22:::1;706:10:::0;55810:12:::1;55801:22;::::0;-1:-1:-1;;;;;4463:32:1;;;4445:51;;4433:2;4418:18;55801:22:0::1;;;;;;;55711:120::o:0;38583:399::-;-1:-1:-1;;;;;38667:21:0;;38659:65;;;;-1:-1:-1;;;38659:65:0;;15634:2:1;38659:65:0;;;15616:21:1;15673:2;15653:18;;;15646:30;15712:33;15692:18;;;15685:61;15763:18;;38659:65:0;15606:181:1;38659:65:0;38737:49;38766:1;38770:7;38779:6;38737:20;:49::i;:::-;38815:6;38799:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;38832:18:0;;;;;;:9;:18;;;;;:28;;38854:6;;38832:18;:28;;38854:6;;38832:28;:::i;:::-;;;;-1:-1:-1;;38876:37:0;;4845:25:1;;;-1:-1:-1;;;;;38876:37:0;;;38893:1;;38876:37;;4833:2:1;4818:18;38876:37:0;;;;;;;62356:205;;:::o;39315:591::-;-1:-1:-1;;;;;39399:21:0;;39391:67;;;;-1:-1:-1;;;39391:67:0;;13175:2:1;39391:67:0;;;13157:21:1;13214:2;13194:18;;;13187:30;13253:34;13233:18;;;13226:62;-1:-1:-1;;;13304:18:1;;;13297:31;13345:19;;39391:67:0;13147:223:1;39391:67:0;39471:49;39492:7;39509:1;39513:6;39471:20;:49::i;:::-;-1:-1:-1;;;;;39558:18:0;;39533:22;39558:18;;;:9;:18;;;;;;39595:24;;;;39587:71;;;;-1:-1:-1;;;39587:71:0;;8431:2:1;39587:71:0;;;8413:21:1;8470:2;8450:18;;;8443:30;8509:34;8489:18;;;8482:62;-1:-1:-1;;;8560:18:1;;;8553:32;8602:19;;39587:71:0;8403:224:1;39587:71:0;-1:-1:-1;;;;;39694:18:0;;;;;;:9;:18;;;;;39715:23;;;39694:44;;39760:12;:22;;39732:6;;39694:18;39760:22;;39732:6;;39760:22;:::i;:::-;;;;-1:-1:-1;;39800:37:0;;4845:25:1;;;39826:1:0;;-1:-1:-1;;;;;39800:37:0;;;;;4833:2:1;4818:18;39800:37:0;;;;;;;52738:31;52612:165;;:::o;55452:118::-;54723:7;;;;54977:9;54969:38;;;;-1:-1:-1;;;54969:38:0;;10831:2:1;54969:38:0;;;10813:21:1;10870:2;10850:18;;;10843:30;-1:-1:-1;;;10889:18:1;;;10882:46;10945:18;;54969:38:0;10803:166:1;54969:38:0;55512:7:::1;:14:::0;;-1:-1:-1;;55512:14:0::1;55522:4;55512:14;::::0;;55542:20:::1;55549:12;706:10:::0;;626:98;21403:146;21474:7;21518:22;21522:3;21534:5;21518:3;:22::i;20963:108::-;21026:4;21046:19;21054:3;18010:18;;17934:100;60580:207;-1:-1:-1;;;;;60701:14:0;;60640:15;60701:14;;;:7;:14;;;;;1719;;1842:1;1824:19;;;;1719:14;60762:17;60657:130;60580:207;;;:::o;11856:161::-;11933:7;11956:55;11978:20;:18;:20::i;:::-;12000:10;7696:57;;-1:-1:-1;;;7696:57:0;;;3369:27:1;3412:11;;;3405:27;;;3448:12;;;3441:28;;;7660:7:0;;3485:12:1;;7696:57:0;;;;;;;;;;;;7686:68;;;;;;7679:75;;7552:208;;;;;5272:1413;5382:7;6272:66;6261:77;;;6245:145;;;;-1:-1:-1;;;6245:145:0;;10428:2:1;6245:145:0;;;10410:21:1;10467:2;10447:18;;;10440:30;10506:34;10486:18;;;10479:62;-1:-1:-1;;;10557:18:1;;;10550:32;10599:19;;6245:145:0;10400:224:1;6245:145:0;6405:1;:7;;6410:2;6405:7;:18;;;;6416:1;:7;;6421:2;6416:7;6405:18;6397:65;;;;-1:-1:-1;;;6397:65:0;;11176:2:1;6397:65:0;;;11158:21:1;11215:2;11195:18;;;11188:30;11254:34;11234:18;;;11227:62;-1:-1:-1;;;11305:18:1;;;11298:32;11347:19;;6397:65:0;11148:224:1;6397:65:0;6569:24;;;6552:14;6569:24;;;;;;;;;6198:25:1;;;6271:4;6259:17;;6239:18;;;6232:45;;;;6293:18;;;6286:34;;;6336:18;;;6329:34;;;6569:24:0;;6170:19:1;;6569:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6569:24:0;;-1:-1:-1;;6569:24:0;;;-1:-1:-1;;;;;;;6608:20:0;;6600:57;;;;-1:-1:-1;;;6600:57:0;;6964:2:1;6600:57:0;;;6946:21:1;7003:2;6983:18;;;6976:30;7042:26;7022:18;;;7015:54;7086:18;;6600:57:0;6936:174:1;6600:57:0;6673:6;5272:1413;-1:-1:-1;;;;;5272:1413:0:o;48202:166::-;47522:7;47545:12;;;;;;;;;;:22;;;46096:30;46107:4;706:10;46096;:30::i;:::-;48336:26:::1;48348:4;48354:7;48336:11;:26::i;50019:207::-:0;50090:22;50098:4;50104:7;50090;:22::i;:::-;50085:136;;50123:6;:12;;;;;;;;;;;-1:-1:-1;;;;;50123:29:0;;;;;;;;;:36;;-1:-1:-1;;50123:36:0;50155:4;50123:36;;;50200:12;706:10;;626:98;50200:12;-1:-1:-1;;;;;50173:40:0;50191:7;-1:-1:-1;;;;;50173:40:0;50185:4;50173:40;;;;;;;;;;50019:207;;:::o;15864:364::-;15927:4;17826:19;;;:12;;;:19;;;;;;15940:283;;-1:-1:-1;15977:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;16142:18;;16120:19;;;:12;;;:19;;;;;;:40;;;;16169:11;;15940:283;-1:-1:-1;16210:5:0;16203:12;;63721:222;63875:62;63920:4;63926:2;63930:6;63875:44;:62::i;46893:388::-;46970:22;46978:4;46984:7;46970;:22::i;:::-;46965:311;;47110:41;47138:7;-1:-1:-1;;;;;47110:41:0;47148:2;47110:19;:41::i;:::-;47200:35;47225:4;47232:2;47200:19;:35::i;:::-;47039:209;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;47039:209:0;;;;;;;;;;-1:-1:-1;;;47003:265:0;;;;;;;:::i;50232:208::-;50303:22;50311:4;50317:7;50303;:22::i;:::-;50299:136;;;50368:5;50336:12;;;;;;;;;;;-1:-1:-1;;;;;50336:29:0;;;;;;;;;;:37;;-1:-1:-1;;50336:37:0;;;50387:40;706:10;;50336:12;;50387:40;;50368:5;50387:40;50232:208;;:::o;16390:1265::-;16456:4;16584:19;;;:12;;;:19;;;;;;16616:15;;16612:1038;;16961:18;16982:14;16995:1;16982:10;:14;:::i;:::-;17022:18;;16961:35;;-1:-1:-1;17005:14:0;;17022:22;;17043:1;;17022:22;:::i;:::-;17005:39;;17072:13;17059:9;:26;17055:359;;17098:17;17118:3;:11;;17130:9;17118:22;;;;;;;;:::i;:::-;;;;;;;;;17098:42;;17256:9;17227:3;:11;;17239:13;17227:26;;;;;;;;:::i;:::-;;;;;;;;;;;;:38;;;;17325:23;;;:12;;;:23;;;;;:36;;;17055:359;17483:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;17566:3;:12;;:19;17579:5;17566:19;;;;;;;;;;;17559:26;;;17603:4;17596:11;;;;;;;16612:1038;17637:5;17630:12;;;;;18366:111;18430:7;18453:3;:11;;18465:5;18453:18;;;;;;;;:::i;:::-;;;;;;;;;18446:25;;18366:111;;;;:::o;63351:217::-;63516:44;63543:4;63549:2;63553:6;63516:26;:44::i;26258:400::-;26327:13;26349:19;26381:10;26385:6;26381:1;:10;:::i;:::-;:14;;26394:1;26381:14;:::i;:::-;26371:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;26371:25:0;;26349:47;;-1:-1:-1;;;26403:6:0;26410:1;26403:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;26403:15:0;;;;;;;;;-1:-1:-1;;;26425:6:0;26432:1;26425:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;26425:15:0;;;;;;;;-1:-1:-1;26452:6:0;26461:10;26465:6;26461:1;:10;:::i;:::-;:14;;26474:1;26461:14;:::i;:::-;26452:23;;26447:116;26481:1;26477;:5;26447:116;;;-1:-1:-1;;;26523:5:0;26531:3;26523:11;26510:25;;;;;;;:::i;:::-;;;;26498:6;26505:1;26498:9;;;;;;;;:::i;:::-;;;;:37;-1:-1:-1;;;;;26498:37:0;;;;;;;;-1:-1:-1;26554:1:0;26544:11;;;;;26484:3;;;:::i;:::-;;;26447:116;;;-1:-1:-1;26577:10:0;;26569:55;;;;-1:-1:-1;;;26569:55:0;;7317:2:1;26569:55:0;;;7299:21:1;;;7336:18;;;7329:30;7395:34;7375:18;;;7368:62;7447:18;;26569:55:0;7289:182:1;56429:272:0;54723:7;;;;56637:9;56629:64;;;;-1:-1:-1;;;56629:64:0;;15994:2:1;56629:64:0;;;15976:21:1;16033:2;16013:18;;;16006:30;16072:34;16052:18;;;16045:62;-1:-1:-1;;;16123:18:1;;;16116:40;16173:19;;56629:64:0;15966:232:1;14:173;82:20;;-1:-1:-1;;;;;131:31:1;;121:42;;111:2;;177:1;174;167:12;111:2;63:124;;;:::o;192:186::-;251:6;304:2;292:9;283:7;279:23;275:32;272:2;;;320:1;317;310:12;272:2;343:29;362:9;343:29;:::i;383:260::-;451:6;459;512:2;500:9;491:7;487:23;483:32;480:2;;;528:1;525;518:12;480:2;551:29;570:9;551:29;:::i;:::-;541:39;;599:38;633:2;622:9;618:18;599:38;:::i;:::-;589:48;;470:173;;;;;:::o;648:328::-;725:6;733;741;794:2;782:9;773:7;769:23;765:32;762:2;;;810:1;807;800:12;762:2;833:29;852:9;833:29;:::i;:::-;823:39;;881:38;915:2;904:9;900:18;881:38;:::i;:::-;871:48;;966:2;955:9;951:18;938:32;928:42;;752:224;;;;;:::o;981:693::-;1092:6;1100;1108;1116;1124;1132;1140;1193:3;1181:9;1172:7;1168:23;1164:33;1161:2;;;1210:1;1207;1200:12;1161:2;1233:29;1252:9;1233:29;:::i;:::-;1223:39;;1281:38;1315:2;1304:9;1300:18;1281:38;:::i;:::-;1271:48;;1366:2;1355:9;1351:18;1338:32;1328:42;;1417:2;1406:9;1402:18;1389:32;1379:42;;1471:3;1460:9;1456:19;1443:33;1516:4;1509:5;1505:16;1498:5;1495:27;1485:2;;1536:1;1533;1526:12;1485:2;1151:523;;;;-1:-1:-1;1151:523:1;;;;1559:5;1611:3;1596:19;;1583:33;;-1:-1:-1;1663:3:1;1648:19;;;1635:33;;1151:523;-1:-1:-1;;1151:523:1:o;1679:254::-;1747:6;1755;1808:2;1796:9;1787:7;1783:23;1779:32;1776:2;;;1824:1;1821;1814:12;1776:2;1847:29;1866:9;1847:29;:::i;:::-;1837:39;1923:2;1908:18;;;;1895:32;;-1:-1:-1;;;1766:167:1:o;1938:180::-;1997:6;2050:2;2038:9;2029:7;2025:23;2021:32;2018:2;;;2066:1;2063;2056:12;2018:2;-1:-1:-1;2089:23:1;;2008:110;-1:-1:-1;2008:110:1:o;2123:254::-;2191:6;2199;2252:2;2240:9;2231:7;2227:23;2223:32;2220:2;;;2268:1;2265;2258:12;2220:2;2304:9;2291:23;2281:33;;2333:38;2367:2;2356:9;2352:18;2333:38;:::i;2382:248::-;2450:6;2458;2511:2;2499:9;2490:7;2486:23;2482:32;2479:2;;;2527:1;2524;2517:12;2479:2;-1:-1:-1;;2550:23:1;;;2620:2;2605:18;;;2592:32;;-1:-1:-1;2469:161:1:o;2635:286::-;2693:6;2746:2;2734:9;2725:7;2721:23;2717:32;2714:2;;;2762:1;2759;2752:12;2714:2;2788:23;;-1:-1:-1;;;;;;2840:32:1;;2830:43;;2820:2;;2887:1;2884;2877:12;3508:786;3919:25;3914:3;3907:38;3889:3;3974:6;3968:13;3990:62;4045:6;4040:2;4035:3;4031:12;4024:4;4016:6;4012:17;3990:62;:::i;:::-;-1:-1:-1;;;4111:2:1;4071:16;;;4103:11;;;4096:40;4161:13;;4183:63;4161:13;4232:2;4224:11;;4217:4;4205:17;;4183:63;:::i;:::-;4266:17;4285:2;4262:26;;3897:397;-1:-1:-1;;;;3897:397:1:o;6374:383::-;6523:2;6512:9;6505:21;6486:4;6555:6;6549:13;6598:6;6593:2;6582:9;6578:18;6571:34;6614:66;6673:6;6668:2;6657:9;6653:18;6648:2;6640:6;6636:15;6614:66;:::i;:::-;6741:2;6720:15;-1:-1:-1;;6716:29:1;6701:45;;;;6748:2;6697:54;;6495:262;-1:-1:-1;;6495:262:1:o;16574:128::-;16614:3;16645:1;16641:6;16638:1;16635:13;16632:2;;;16651:18;;:::i;:::-;-1:-1:-1;16687:9:1;;16622:80::o;16707:168::-;16747:7;16813:1;16809;16805:6;16801:14;16798:1;16795:21;16790:1;16783:9;16776:17;16772:45;16769:2;;;16820:18;;:::i;:::-;-1:-1:-1;16860:9:1;;16759:116::o;16880:125::-;16920:4;16948:1;16945;16942:8;16939:2;;;16953:18;;:::i;:::-;-1:-1:-1;16990:9:1;;16929:76::o;17010:258::-;17082:1;17092:113;17106:6;17103:1;17100:13;17092:113;;;17182:11;;;17176:18;17163:11;;;17156:39;17128:2;17121:10;17092:113;;;17223:6;17220:1;17217:13;17214:2;;;-1:-1:-1;;17258:1:1;17240:16;;17233:27;17063:205::o;17273:136::-;17312:3;17340:5;17330:2;;17349:18;;:::i;:::-;-1:-1:-1;;;17385:18:1;;17320:89::o;17414:380::-;17493:1;17489:12;;;;17536;;;17557:2;;17611:4;17603:6;17599:17;17589:27;;17557:2;17664;17656:6;17653:14;17633:18;17630:38;17627:2;;;17710:10;17705:3;17701:20;17698:1;17691:31;17745:4;17742:1;17735:15;17773:4;17770:1;17763:15;17799:127;17860:10;17855:3;17851:20;17848:1;17841:31;17891:4;17888:1;17881:15;17915:4;17912:1;17905:15;17931:127;17992:10;17987:3;17983:20;17980:1;17973:31;18023:4;18020:1;18013:15;18047:4;18044:1;18037:15;18063:127;18124:10;18119:3;18115:20;18112:1;18105:31;18155:4;18152:1;18145:15;18179:4;18176:1;18169:15;18195:127;18256:10;18251:3;18247:20;18244:1;18237:31;18287:4;18284:1;18277:15;18311:4;18308:1;18301:15

Swarm Source

ipfs://a2d4c1d6ed02f2295f2da9e5b8aa1e158ec0e201c1086d52d1e9dd1322f0f046
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ 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.