POL Price: $0.641826 (-8.83%)
 

Overview

Max Total Supply

1,448,111,254,177.86395452293226104 DLYCOP

Holders

114,033 ( -0.004%)

Market

Price

$0.00 @ 0.000006 POL

Onchain Market Cap

$5,951,737.25

Circulating Supply Market Cap

$0.00

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
Mapper: USDT Stablecoin
Balance
165,992,366.411297335772745729 DLYCOP

Value
$682.23 ( ~1,062.9516 POL) [0.0115%]
0xc2132d05d31c914a87c6611c10748aeb04b58e8f
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Daily COP is a stablecoin pegged to the Colombian Peso to modernise and globalise the local currency for all Colombians.

Market

Volume (24H):$1,665.17
Market Capitalization:$0.00
Circulating Supply:0.00 DLYCOP
Market Data Source: Coinmarketcap

Contract Source Code Verified (Exact Match)

Contract Name:
DailyCopTokenChild

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at polygonscan.com on 2021-08-28
*/

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

// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]

// SPDX-License-Identifier: MIT

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,
		uint256 value,
		uint256 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 (uint256);

	/**
	 * @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/contracts/token/ERC20/[email protected]

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/contracts/token/ERC20/extensions/[email protected]

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/contracts/utils/[email protected]

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/contracts/token/ERC20/[email protected]

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/contracts/utils/cryptography/[email protected]

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(
			uint256(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/contracts/utils/cryptography/[email protected]

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;
	uint256 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/contracts/utils/[email protected]

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
		uint256 _value; // default: 0
	}

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

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

	function decrement(Counter storage counter) internal {
		uint256 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/contracts/token/ERC20/extensions/[email protected]

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/contracts/token/ERC20/extensions/[email protected]

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/contracts/utils/[email protected]

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(uint256 value) internal pure returns (string memory) {
		// Inspired by OraclizeAPI's implementation - MIT licence
		// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

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

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

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

// File @openzeppelin/contracts/utils/introspection/[email protected]

pragma solidity ^0.8.0;

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

// File @openzeppelin/contracts/utils/introspection/[email protected]

pragma solidity ^0.8.0;

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

// File @openzeppelin/contracts/access/[email protected]

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(uint256(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/contracts/utils/structs/[email protected]

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 => uint256) _indexes;
	}

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

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

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

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

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

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

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

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

			return true;
		} else {
			return false;
		}
	}

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

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

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

	// Bytes32Set

	struct Bytes32Set {
		Set _inner;
	}

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

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

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

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

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

	// AddressSet

	struct AddressSet {
		Set _inner;
	}

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

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

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

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

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

	// UintSet

	struct UintSet {
		Set _inner;
	}

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

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

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

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

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

// File @openzeppelin/contracts/access/[email protected]

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/contracts/utils/math/[email protected]

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
	/**
	 * @dev Returns the largest of two numbers.
	 */
	function max(uint256 a, uint256 b) internal pure returns (uint256) {
		return a >= b ? a : b;
	}

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

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

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

// File @openzeppelin/contracts/utils/[email protected]

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to array types.
 */
library Arrays {
	/**
	 * @dev Searches a sorted `array` and returns the first index that contains
	 * a value greater or equal to `element`. If no such index exists (i.e. all
	 * values in the array are strictly less than `element`), the array length is
	 * returned. Time complexity O(log n).
	 *
	 * `array` is expected to be sorted in ascending order, and to contain no
	 * repeated elements.
	 */
	function findUpperBound(uint256[] storage array, uint256 element)
		internal
		view
		returns (uint256)
	{
		if (array.length == 0) {
			return 0;
		}

		uint256 low = 0;
		uint256 high = array.length;

		while (low < high) {
			uint256 mid = Math.average(low, high);

			// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
			// because Math.average rounds down (it does integer division with truncation).
			if (array[mid] > element) {
				high = mid;
			} else {
				low = mid + 1;
			}
		}

		// At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
		if (low > 0 && array[low - 1] == element) {
			return low - 1;
		} else {
			return low;
		}
	}
}

// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]

pragma solidity ^0.8.0;

/**
 * @dev This contract extends an ERC20 token with a snapshot mechanism. When a snapshot is created, the balances and
 * total supply at the time are recorded for later access.
 *
 * This can be used to safely create mechanisms based on token balances such as trustless dividends or weighted voting.
 * In naive implementations it's possible to perform a "double spend" attack by reusing the same balance from different
 * accounts. By using snapshots to calculate dividends or voting power, those attacks no longer apply. It can also be
 * used to create an efficient ERC20 forking mechanism.
 *
 * Snapshots are created by the internal {_snapshot} function, which will emit the {Snapshot} event and return a
 * snapshot id. To get the total supply at the time of a snapshot, call the function {totalSupplyAt} with the snapshot
 * id. To get the balance of an account at the time of a snapshot, call the {balanceOfAt} function with the snapshot id
 * and the account address.
 *
 * NOTE: Snapshot policy can be customized by overriding the {_getCurrentSnapshotId} method. For example, having it
 * return `block.number` will trigger the creation of snapshot at the begining of each new block. When overridding this
 * function, be careful about the monotonicity of its result. Non-monotonic snapshot ids will break the contract.
 *
 * Implementing snapshots for every block using this method will incur significant gas costs. For a gas-efficient
 * alternative consider {ERC20Votes}.
 *
 * ==== Gas Costs
 *
 * Snapshots are efficient. Snapshot creation is _O(1)_. Retrieval of balances or total supply from a snapshot is _O(log
 * n)_ in the number of snapshots that have been created, although _n_ for a specific account will generally be much
 * smaller since identical balances in subsequent snapshots are stored as a single entry.
 *
 * There is a constant overhead for normal ERC20 transfers due to the additional snapshot bookkeeping. This overhead is
 * only significant for the first transfer that immediately follows a snapshot for a particular account. Subsequent
 * transfers will have normal cost until the next snapshot, and so on.
 */

abstract contract ERC20Snapshot is ERC20 {
	// Inspired by Jordi Baylina's MiniMeToken to record historical balances:
	// https://github.com/Giveth/minimd/blob/ea04d950eea153a04c51fa510b068b9dded390cb/contracts/MiniMeToken.sol

	using Arrays for uint256[];
	using Counters for Counters.Counter;

	// Snapshotted values have arrays of ids and the value corresponding to that id. These could be an array of a
	// Snapshot struct, but that would impede usage of functions that work on an array.
	struct Snapshots {
		uint256[] ids;
		uint256[] values;
	}

	mapping(address => Snapshots) private _accountBalanceSnapshots;
	Snapshots private _totalSupplySnapshots;

	// Snapshot ids increase monotonically, with the first value being 1. An id of 0 is invalid.
	Counters.Counter private _currentSnapshotId;

	/**
	 * @dev Emitted by {_snapshot} when a snapshot identified by `id` is created.
	 */
	event Snapshot(uint256 id);

	/**
	 * @dev Creates a new snapshot and returns its snapshot id.
	 *
	 * Emits a {Snapshot} event that contains the same id.
	 *
	 * {_snapshot} is `internal` and you have to decide how to expose it externally. Its usage may be restricted to a
	 * set of accounts, for example using {AccessControl}, or it may be open to the public.
	 *
	 * [WARNING]
	 * ====
	 * While an open way of calling {_snapshot} is required for certain trust minimization mechanisms such as forking,
	 * you must consider that it can potentially be used by attackers in two ways.
	 *
	 * First, it can be used to increase the cost of retrieval of values from snapshots, although it will grow
	 * logarithmically thus rendering this attack ineffective in the long term. Second, it can be used to target
	 * specific accounts and increase the cost of ERC20 transfers for them, in the ways specified in the Gas Costs
	 * section above.
	 *
	 * We haven't measured the actual numbers; if this is something you're interested in please reach out to us.
	 * ====
	 */
	function _snapshot() internal virtual returns (uint256) {
		_currentSnapshotId.increment();

		uint256 currentId = _getCurrentSnapshotId();
		emit Snapshot(currentId);
		return currentId;
	}

	/**
	 * @dev Get the current snapshotId
	 */
	function _getCurrentSnapshotId() internal view virtual returns (uint256) {
		return _currentSnapshotId.current();
	}

	/**
	 * @dev Retrieves the balance of `account` at the time `snapshotId` was created.
	 */
	function balanceOfAt(address account, uint256 snapshotId)
		public
		view
		virtual
		returns (uint256)
	{
		(bool snapshotted, uint256 value) = _valueAt(
			snapshotId,
			_accountBalanceSnapshots[account]
		);

		return snapshotted ? value : balanceOf(account);
	}

	/**
	 * @dev Retrieves the total supply at the time `snapshotId` was created.
	 */
	function totalSupplyAt(uint256 snapshotId)
		public
		view
		virtual
		returns (uint256)
	{
		(bool snapshotted, uint256 value) = _valueAt(
			snapshotId,
			_totalSupplySnapshots
		);

		return snapshotted ? value : totalSupply();
	}

	// Update balance and/or total supply snapshots before the values are modified. This is implemented
	// in the _beforeTokenTransfer hook, which is executed for _mint, _burn, and _transfer operations.
	function _beforeTokenTransfer(
		address from,
		address to,
		uint256 amount
	) internal virtual override {
		super._beforeTokenTransfer(from, to, amount);

		if (from == address(0)) {
			// mint
			_updateAccountSnapshot(to);
			_updateTotalSupplySnapshot();
		} else if (to == address(0)) {
			// burn
			_updateAccountSnapshot(from);
			_updateTotalSupplySnapshot();
		} else {
			// transfer
			_updateAccountSnapshot(from);
			_updateAccountSnapshot(to);
		}
	}

	function _valueAt(uint256 snapshotId, Snapshots storage snapshots)
		private
		view
		returns (bool, uint256)
	{
		require(snapshotId > 0, "ERC20Snapshot: id is 0");
		require(
			snapshotId <= _getCurrentSnapshotId(),
			"ERC20Snapshot: nonexistent id"
		);

		// When a valid snapshot is queried, there are three possibilities:
		//  a) The queried value was not modified after the snapshot was taken. Therefore, a snapshot entry was never
		//  created for this id, and all stored snapshot ids are smaller than the requested one. The value that corresponds
		//  to this id is the current one.
		//  b) The queried value was modified after the snapshot was taken. Therefore, there will be an entry with the
		//  requested id, and its value is the one to return.
		//  c) More snapshots were created after the requested one, and the queried value was later modified. There will be
		//  no entry for the requested id: the value that corresponds to it is that of the smallest snapshot id that is
		//  larger than the requested one.
		//
		// In summary, we need to find an element in an array, returning the index of the smallest value that is larger if
		// it is not found, unless said value doesn't exist (e.g. when all values are smaller). Arrays.findUpperBound does
		// exactly this.

		uint256 index = snapshots.ids.findUpperBound(snapshotId);

		if (index == snapshots.ids.length) {
			return (false, 0);
		} else {
			return (true, snapshots.values[index]);
		}
	}

	function _updateAccountSnapshot(address account) private {
		_updateSnapshot(_accountBalanceSnapshots[account], balanceOf(account));
	}

	function _updateTotalSupplySnapshot() private {
		_updateSnapshot(_totalSupplySnapshots, totalSupply());
	}

	function _updateSnapshot(Snapshots storage snapshots, uint256 currentValue)
		private
	{
		uint256 currentId = _getCurrentSnapshotId();
		if (_lastSnapshotId(snapshots.ids) < currentId) {
			snapshots.ids.push(currentId);
			snapshots.values.push(currentValue);
		}
	}

	function _lastSnapshotId(uint256[] storage ids)
		private
		view
		returns (uint256)
	{
		if (ids.length == 0) {
			return 0;
		} else {
			return ids[ids.length - 1];
		}
	}
}

// File contracts/interfaces/IChildToken.sol

pragma solidity 0.8.4;

interface IChildToken is IERC20 {
	/**
	 * @notice called when token is deposited on root chain
	 * @dev Should be callable only by ChildChainManager
	 * Should handle deposit by minting the required amount for user, not to create new tokens,
	 * but to move tokens previously swapped to the root chain back to the child chain
	 * @param user user address for whom deposit is being done
	 * @param depositData abi encoded amount
	 */
	function deposit(address user, bytes calldata depositData) external;
}

// File contracts/token/DailyCopTokenChild.sol

pragma solidity 0.8.4;

contract DailyCopTokenChild is
	AccessControlEnumerable,
	ERC20Burnable,
	ERC20Snapshot,
	ERC20Permit,
	IChildToken
{
	uint256 private _layer1Supply;

	// Roles
	bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
	bytes32 public constant DEPOSITOR_ROLE = keccak256("DEPOSITOR_ROLE");
	bytes32 public constant SNAPSHOT_ROLE = keccak256("SNAPSHOT_ROLE");

	modifier notThisAddress(address account) {
		require(
			account != address(this),
			"Address can not be the token contract's address"
		);
		_;
	}

	constructor(
		address defaultAdmin,
		address minter,
		address childChainManager
	) ERC20("Daily COP", "DLYCOP") ERC20Permit("DailyCopToken") {
		_setupRole(DEFAULT_ADMIN_ROLE, defaultAdmin);
		_setupRole(MINTER_ROLE, minter);

		// Only the child chain manager knows when a token is deposited on the root chain
		_setupRole(DEPOSITOR_ROLE, childChainManager);
	}

	/** @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.
	 * - `msg.sender` should have the minter role (MINTER_ROLE).
	 */
	function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
		_mint(to, amount);
	}

	/**
	 * @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(ERC20, IERC20)
		notThisAddress(recipient)
		returns (bool)
	{
		return super.transfer(recipient, amount);
	}

	/**
	 * @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(ERC20, IERC20)
		notThisAddress(recipient)
		returns (bool)
	{
		return super.transferFrom(sender, recipient, amount);
	}

	/**
	 * @dev Creates a new snapshot and returns its snapshot id.
	 *
	 * Emits a {Snapshot} event that contains the same id.
	 *
	 * {_snapshot} is `internal` and you have to decide how to expose it externally. Its usage may be restricted to a
	 * set of accounts, for example using {AccessControl}, or it may be open to the public.
	 *
	 * [WARNING]
	 * ====
	 * While an open way of calling {_snapshot} is required for certain trust minimization mechanisms such as forking,
	 * you must consider that it can potentially be used by attackers in two ways.
	 *
	 * First, it can be used to increase the cost of retrieval of values from snapshots, although it will grow
	 * logarithmically thus rendering this attack ineffective in the long term. Second, it can be used to target
	 * specific accounts and increase the cost of ERC20 transfers for them, in the ways specified in the Gas Costs
	 * section above.
	 *
	 * We haven't measured the actual numbers; if this is something you're interested in please reach out to us.
	 * ====
	 */
	function snapshot() public onlyRole(SNAPSHOT_ROLE) {
		_snapshot();
	}

	/**
	 * @notice called when token is deposited on root chain
	 * @dev Should be callable only by ChildChainManager
	 * Should handle deposit by minting the required amount for user, not to create new tokens,
	 * but to move tokens previously swapped to the root chain back to the child chain
	 * @param user user address for whom deposit is being done
	 * @param depositData abi encoded amount
	 */
	function deposit(address user, bytes calldata depositData)
		external
		override
		onlyRole(DEPOSITOR_ROLE)
	{
		uint256 amount = abi.decode(depositData, (uint256));
		// Keep track of token supply on layer 1 (root chain)
		_layer1Supply -= amount;
		_mint(user, amount);
	}

	/**
	 * @notice called when user wants to withdraw tokens back to root chain
	 * @dev Should burn user's tokens. This transaction will be verified when exiting on root chain
	 * @param amount amount of tokens to withdraw
	 */
	function withdraw(uint256 amount) external {
		// Keep track of token supply on layer 1 (root chain)
		_layer1Supply += amount;
		_burn(_msgSender(), amount);
	}

	/**
	 * @notice called when admin wants to unlock erc20 tokens owned by the contract
	 * @param _tokenAddress the address of the tokens to unlock
	 * @param _to the address to send the tokens to
	 * @param _amount amount of tokens to unlock
	 */
	function transferAnyERC20(
		address _tokenAddress,
		address _to,
		uint256 _amount
	) public onlyRole(DEFAULT_ADMIN_ROLE) {
		IERC20(_tokenAddress).transfer(_to, _amount);
	}

	/**
	 * @notice Obtain the supply of tokens that were moved to layer 1 (Ethereum) through the Polygon PoS bridge.
	 */
	function layer1Supply() public view returns (uint256) {
		return _layer1Supply;
	}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"defaultAdmin","type":"address"},{"internalType":"address","name":"minter","type":"address"},{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":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":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Snapshot","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"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_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":"SNAPSHOT_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":"address","name":"account","type":"address"},{"internalType":"uint256","name":"snapshotId","type":"uint256"}],"name":"balanceOfAt","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":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"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":[],"name":"layer1Supply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[{"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":[],"name":"snapshot","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":"uint256","name":"snapshotId","type":"uint256"}],"name":"totalSupplyAt","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":"_tokenAddress","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferAnyERC20","outputs":[],"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":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101406040527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9610120908152503480156200003a57600080fd5b5060405162004d0338038062004d03833981810160405281019062000060919062000606565b6040518060400160405280600d81526020017f4461696c79436f70546f6b656e00000000000000000000000000000000000000815250806040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600981526020017f4461696c7920434f5000000000000000000000000000000000000000000000008152506040518060400160405280600681526020017f444c59434f5000000000000000000000000000000000000000000000000000008152508160059080519060200190620001519291906200053f565b5080600690805190602001906200016a9291906200053f565b50505060008280519060200120905060008280519060200120905060007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f90508260c081815250508160e081815250504660a08181525050620001d58184846200026d60201b60201c565b60808181525050806101008181525050505050505050620002006000801b84620002a960201b60201c565b620002327f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a683620002a960201b60201c565b620002647f8f4f2da22e8ac8f11e15f9fc141cddbb5deea8800186560abb6e68c5496619a982620002a960201b60201c565b505050620007b3565b600083838346306040516020016200028a9594939291906200068f565b6040516020818303038152906040528051906020012090509392505050565b620002c08282620002f160201b6200130b1760201c565b620002ec81600160008581526020019081526020016000206200030760201b620013191790919060201c565b505050565b6200030382826200033f60201b60201c565b5050565b600062000337836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6200043060201b60201c565b905092915050565b620003518282620004aa60201b60201c565b6200042c57600160008084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550620003d16200051460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60006200044483836200051c60201b60201c565b6200049f578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050620004a4565b600090505b92915050565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600033905090565b600080836001016000848152602001908152602001600020541415905092915050565b8280546200054d9062000734565b90600052602060002090601f016020900481019282620005715760008555620005bd565b82601f106200058c57805160ff1916838001178555620005bd565b82800160010185558215620005bd579182015b82811115620005bc5782518255916020019190600101906200059f565b5b509050620005cc9190620005d0565b5090565b5b80821115620005eb576000816000905550600101620005d1565b5090565b600081519050620006008162000799565b92915050565b6000806000606084860312156200061c57600080fd5b60006200062c86828701620005ef565b93505060206200063f86828701620005ef565b92505060406200065286828701620005ef565b9150509250925092565b6200066781620006ec565b82525050565b620006788162000700565b82525050565b62000689816200072a565b82525050565b600060a082019050620006a660008301886200066d565b620006b560208301876200066d565b620006c460408301866200066d565b620006d360608301856200067e565b620006e260808301846200065c565b9695505050505050565b6000620006f9826200070a565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060028204905060018216806200074d57607f821691505b602082108114156200076457620007636200076a565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b620007a481620006ec565b8114620007b057600080fd5b50565b60805160a05160c05160e0516101005161012051614500620008036000396000611131015260006118e7015260006119290152600061190801526000611894015260006118bc01526145006000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c806379cc679011610125578063a3b0b5a3116100ad578063cf2c52cb1161007c578063cf2c52cb1461069d578063d505accf146106b9578063d5391393146106d5578063d547741f146106f3578063dd62ed3e1461070f5761021c565b8063a3b0b5a3146105ef578063a457c2d71461060d578063a9059cbb1461063d578063ca15c8731461066d5761021c565b806395d89b41116100f457806395d89b411461055b5780639711715a14610579578063981b24d0146105835780639e17a433146105b3578063a217fddf146105d15761021c565b806379cc6790146104af5780637ecebe00146104cb5780639010d07c146104fb57806391d148541461052b5761021c565b80633644e515116101a857806342966c681161017757806342966c68146103f95780634ee2cd7e146104155780635b6f547e146104455780637028e2cd1461046157806370a082311461047f5761021c565b80633644e5151461037357806336568abe1461039157806339509351146103ad57806340c10f19146103dd5761021c565b806323b872dd116101ef57806323b872dd146102bd578063248a9ca3146102ed5780632e1a7d4d1461031d5780632f2ff15d14610339578063313ce567146103555761021c565b806301ffc9a71461022157806306fdde0314610251578063095ea7b31461026f57806318160ddd1461029f575b600080fd5b61023b600480360381019061023691906131e3565b61073f565b60405161024891906136fe565b60405180910390f35b6102596107b9565b604051610266919061382d565b60405180910390f35b610289600480360381019061028491906130dd565b61084b565b60405161029691906136fe565b60405180910390f35b6102a7610869565b6040516102b49190613aef565b60405180910390f35b6102d760048036038101906102d29190612f98565b610873565b6040516102e491906136fe565b60405180910390f35b61030760048036038101906103029190613142565b6108fa565b6040516103149190613719565b60405180910390f35b6103376004803603810190610332919061320c565b610919565b005b610353600480360381019061034e919061316b565b610946565b005b61035d61097a565b60405161036a9190613b0a565b60405180910390f35b61037b610983565b6040516103889190613719565b60405180910390f35b6103ab60048036038101906103a6919061316b565b610992565b005b6103c760048036038101906103c291906130dd565b6109c6565b6040516103d491906136fe565b60405180910390f35b6103f760048036038101906103f291906130dd565b610a72565b005b610413600480360381019061040e919061320c565b610ab3565b005b61042f600480360381019061042a91906130dd565b610ac7565b60405161043c9190613aef565b60405180910390f35b61045f600480360381019061045a9190612f98565b610b37565b005b610469610be0565b6040516104769190613719565b60405180910390f35b61049960048036038101906104949190612f33565b610c04565b6040516104a69190613aef565b60405180910390f35b6104c960048036038101906104c491906130dd565b610c4d565b005b6104e560048036038101906104e09190612f33565b610cc8565b6040516104f29190613aef565b60405180910390f35b610515600480360381019061051091906131a7565b610d18565b60405161052291906136ba565b60405180910390f35b6105456004803603810190610540919061316b565b610d47565b60405161055291906136fe565b60405180910390f35b610563610db1565b604051610570919061382d565b60405180910390f35b610581610e43565b005b61059d6004803603810190610598919061320c565b610e81565b6040516105aa9190613aef565b60405180910390f35b6105bb610eb2565b6040516105c89190613aef565b60405180910390f35b6105d9610ebc565b6040516105e69190613719565b60405180910390f35b6105f7610ec3565b6040516106049190613719565b60405180910390f35b610627600480360381019061062291906130dd565b610ee7565b60405161063491906136fe565b60405180910390f35b610657600480360381019061065291906130dd565b610fd2565b60405161066491906136fe565b60405180910390f35b61068760048036038101906106829190613142565b611057565b6040516106949190613aef565b60405180910390f35b6106b760048036038101906106b29190613085565b61107b565b005b6106d360048036038101906106ce9190612fe7565b6110ea565b005b6106dd61122c565b6040516106ea9190613719565b60405180910390f35b61070d6004803603810190610708919061316b565b611250565b005b61072960048036038101906107249190612f5c565b611284565b6040516107369190613aef565b60405180910390f35b60007f5a05180f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107b257506107b182611349565b5b9050919050565b6060600580546107c890613d49565b80601f01602080910402602001604051908101604052809291908181526020018280546107f490613d49565b80156108415780601f1061081657610100808354040283529160200191610841565b820191906000526020600020905b81548152906001019060200180831161082457829003601f168201915b5050505050905090565b600061085f6108586113c3565b84846113cb565b6001905092915050565b6000600454905090565b6000823073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156108e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108dc906138ef565b60405180910390fd5b6108f0858585611596565b9150509392505050565b6000806000838152602001908152602001600020600101549050919050565b80600c600082825461092b9190613b4c565b9250508190555061094361093d6113c3565b8261168e565b50565b6109508282611867565b610975816001600085815260200190815260200160002061131990919063ffffffff16565b505050565b60006012905090565b600061098d611890565b905090565b61099c8282611953565b6109c181600160008581526020019081526020016000206119d690919063ffffffff16565b505050565b6000610a686109d36113c3565b8484600360006109e16113c3565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610a639190613b4c565b6113cb565b6001905092915050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610aa481610a9f6113c3565b611a06565b610aae8383611aa3565b505050565b610ac4610abe6113c3565b8261168e565b50565b6000806000610b1484600760008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611c04565b9150915081610b2b57610b2685610c04565b610b2d565b805b9250505092915050565b6000801b610b4c81610b476113c3565b611a06565b8373ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b8152600401610b879291906136d5565b602060405180830381600087803b158015610ba157600080fd5b505af1158015610bb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd99190613119565b5050505050565b7f5fdbd35e8da83ee755d5e62a539e5ed7f47126abede0b8b10f9ea43dc6eed07f81565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000610c6083610c5b6113c3565b611284565b905081811015610ca5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c9c906139ef565b60405180910390fd5b610cb983610cb16113c3565b8484036113cb565b610cc3838361168e565b505050565b6000610d11600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d20565b9050919050565b6000610d3f8260016000868152602001908152602001600020611d2e90919063ffffffff16565b905092915050565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b606060068054610dc090613d49565b80601f0160208091040260200160405190810160405280929190818152602001828054610dec90613d49565b8015610e395780601f10610e0e57610100808354040283529160200191610e39565b820191906000526020600020905b815481529060010190602001808311610e1c57829003601f168201915b5050505050905090565b7f5fdbd35e8da83ee755d5e62a539e5ed7f47126abede0b8b10f9ea43dc6eed07f610e7581610e706113c3565b611a06565b610e7d611d48565b5050565b6000806000610e91846008611c04565b9150915081610ea757610ea2610869565b610ea9565b805b92505050919050565b6000600c54905090565b6000801b81565b7f8f4f2da22e8ac8f11e15f9fc141cddbb5deea8800186560abb6e68c5496619a981565b60008060036000610ef66113c3565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082811015610fb3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610faa90613a8f565b60405180910390fd5b610fc7610fbe6113c3565b858584036113cb565b600191505092915050565b6000823073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611044576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161103b906138ef565b60405180910390fd5b61104e8484611d9e565b91505092915050565b600061107460016000848152602001908152602001600020611dbc565b9050919050565b7f8f4f2da22e8ac8f11e15f9fc141cddbb5deea8800186560abb6e68c5496619a96110ad816110a86113c3565b611a06565b600083838101906110be919061320c565b905080600c60008282546110d29190613c2d565b925050819055506110e38582611aa3565b5050505050565b8342111561112d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111249061392f565b60405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000088888861115c8c611dd1565b8960405160200161117296959493929190613734565b604051602081830303815290604052805190602001209050600061119582611e2f565b905060006111a582878787611e49565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611215576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120c906139af565b60405180910390fd5b6112208a8a8a6113cb565b50505050505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b61125a8282611fd4565b61127f81600160008581526020019081526020016000206119d690919063ffffffff16565b505050565b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6113158282611ffd565b5050565b6000611341836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6120dd565b905092915050565b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806113bc57506113bb8261214d565b5b9050919050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561143b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161143290613a4f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156114ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114a29061390f565b60405180910390fd5b80600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040516115899190613aef565b60405180910390a3505050565b60006115a38484846121b7565b6000600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006115ee6113c3565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508281101561166e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611665906139cf565b60405180910390fd5b6116828561167a6113c3565b8584036113cb565b60019150509392505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156116fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116f590613a0f565b60405180910390fd5b61170a8260008361243b565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015611791576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611788906138cf565b60405180910390fd5b818103600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081600460008282546117e99190613c2d565b92505081905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161184e9190613aef565b60405180910390a36118628360008461244b565b505050565b611870826108fa565b6118818161187c6113c3565b611a06565b61188b8383611ffd565b505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614156118e2577f00000000000000000000000000000000000000000000000000000000000000009050611950565b61194d7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612450565b90505b90565b61195b6113c3565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146119c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119bf90613aaf565b60405180910390fd5b6119d2828261248a565b5050565b60006119fe836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61256b565b905092915050565b611a108282610d47565b611a9f57611a358173ffffffffffffffffffffffffffffffffffffffff1660146126f1565b611a438360001c60206126f1565b604051602001611a54929190613680565b6040516020818303038152906040526040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a96919061382d565b60405180910390fd5b5050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611b13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b0a90613acf565b60405180910390fd5b611b1f6000838361243b565b8060046000828254611b319190613b4c565b9250508190555080600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611b879190613b4c565b925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611bec9190613aef565b60405180910390a3611c006000838361244b565b5050565b60008060008411611c4a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c4190613a6f565b60405180910390fd5b611c526129eb565b841115611c94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8b9061386f565b60405180910390fd5b6000611cac85856000016129fc90919063ffffffff16565b90508360000180549050811415611cca576000809250925050611d19565b6001846001018281548110611d08577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015492509250505b9250929050565b600081600001549050919050565b6000611d3d8360000183612b22565b60001c905092915050565b6000611d54600a612b73565b6000611d5e6129eb565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb6781604051611d8f9190613aef565b60405180910390a18091505090565b6000611db2611dab6113c3565b84846121b7565b6001905092915050565b6000611dca82600001612b89565b9050919050565b600080600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050611e1e81611d20565b9150611e2981612b73565b50919050565b6000611e42611e3c611890565b83612b9a565b9050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08260001c1115611eb1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea89061396f565b60405180910390fd5b601b8460ff161480611ec65750601c8460ff16145b611f05576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611efc9061398f565b60405180910390fd5b600060018686868660405160008152602001604052604051611f2a94939291906137e8565b6020604051602081039080840390855afa158015611f4c573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611fc8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fbf9061384f565b60405180910390fd5b80915050949350505050565b611fdd826108fa565b611fee81611fe96113c3565b611a06565b611ff8838361248a565b505050565b6120078282610d47565b6120d957600160008084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555061207e6113c3565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60006120e98383612bcd565b612142578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050612147565b600090505b92915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612227576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161221e90613a2f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612297576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161228e906138af565b60405180910390fd5b6122a283838361243b565b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015612329576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123209061394f565b60405180910390fd5b818103600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546123be9190613b4c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516124229190613aef565b60405180910390a361243584848461244b565b50505050565b612446838383612bf0565b505050565b505050565b6000838383463060405160200161246b959493929190613795565b6040516020818303038152906040528051906020012090509392505050565b6124948282610d47565b1561256757600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555061250c6113c3565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b600080836001016000848152602001908152602001600020549050600081146126e557600060018261259d9190613c2d565b90506000600186600001805490506125b59190613c2d565b90508181146126705760008660000182815481106125fc577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905080876000018481548110612646577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b856000018054806126aa577f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506126eb565b60009150505b92915050565b6060600060028360026127049190613bd3565b61270e9190613b4c565b67ffffffffffffffff81111561274d577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561277f5781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106127dd577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110612867577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026128a79190613bd3565b6128b19190613b4c565b90505b600181111561299d577f3031323334353637383961626364656600000000000000000000000000000000600f861660108110612919577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b1a60f81b828281518110612956577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c94508061299690613d1f565b90506128b4565b50600084146129e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129d89061388f565b60405180910390fd5b8091505092915050565b60006129f7600a611d20565b905090565b60008083805490501415612a135760009050612b1c565b600080848054905090505b80821015612a9d576000612a328383612caa565b905084868281548110612a6e577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001541115612a8757809150612a97565b600181612a949190613b4c565b92505b50612a1e565b600082118015612afb57508385600184612ab79190613c2d565b81548110612aee577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154145b15612b1657600182612b0d9190613c2d565b92505050612b1c565b81925050505b92915050565b6000826000018281548110612b60577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905092915050565b6001816000016000828254019250508190555050565b600081600001805490509050919050565b60008282604051602001612baf929190613649565b60405160208183030381529060405280519060200120905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b612bfb838383612d11565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612c4657612c3982612d16565b612c41612d69565b612ca5565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612c9157612c8483612d16565b612c8c612d69565b612ca4565b612c9a83612d16565b612ca382612d16565b5b5b505050565b600060028083612cba9190613d85565b600285612cc79190613d85565b612cd19190613b4c565b612cdb9190613ba2565b600283612ce89190613ba2565b600285612cf59190613ba2565b612cff9190613b4c565b612d099190613b4c565b905092915050565b505050565b612d66600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612d6183610c04565b612d7d565b50565b612d7b6008612d76610869565b612d7d565b565b6000612d876129eb565b905080612d9684600001612df8565b1015612df35782600001819080600181540180825580915050600190039060005260206000200160009091909190915055826001018290806001815401808255809150506001900390600052602060002001600090919091909150555b505050565b60008082805490501415612e0f5760009050612e66565b8160018380549050612e219190613c2d565b81548110612e58577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015490505b919050565b600081359050612e7a81614440565b92915050565b600081519050612e8f81614457565b92915050565b600081359050612ea48161446e565b92915050565b600081359050612eb981614485565b92915050565b60008083601f840112612ed157600080fd5b8235905067ffffffffffffffff811115612eea57600080fd5b602083019150836001820283011115612f0257600080fd5b9250929050565b600081359050612f188161449c565b92915050565b600081359050612f2d816144b3565b92915050565b600060208284031215612f4557600080fd5b6000612f5384828501612e6b565b91505092915050565b60008060408385031215612f6f57600080fd5b6000612f7d85828601612e6b565b9250506020612f8e85828601612e6b565b9150509250929050565b600080600060608486031215612fad57600080fd5b6000612fbb86828701612e6b565b9350506020612fcc86828701612e6b565b9250506040612fdd86828701612f09565b9150509250925092565b600080600080600080600060e0888a03121561300257600080fd5b60006130108a828b01612e6b565b97505060206130218a828b01612e6b565b96505060406130328a828b01612f09565b95505060606130438a828b01612f09565b94505060806130548a828b01612f1e565b93505060a06130658a828b01612e95565b92505060c06130768a828b01612e95565b91505092959891949750929550565b60008060006040848603121561309a57600080fd5b60006130a886828701612e6b565b935050602084013567ffffffffffffffff8111156130c557600080fd5b6130d186828701612ebf565b92509250509250925092565b600080604083850312156130f057600080fd5b60006130fe85828601612e6b565b925050602061310f85828601612f09565b9150509250929050565b60006020828403121561312b57600080fd5b600061313984828501612e80565b91505092915050565b60006020828403121561315457600080fd5b600061316284828501612e95565b91505092915050565b6000806040838503121561317e57600080fd5b600061318c85828601612e95565b925050602061319d85828601612e6b565b9150509250929050565b600080604083850312156131ba57600080fd5b60006131c885828601612e95565b92505060206131d985828601612f09565b9150509250929050565b6000602082840312156131f557600080fd5b600061320384828501612eaa565b91505092915050565b60006020828403121561321e57600080fd5b600061322c84828501612f09565b91505092915050565b61323e81613c61565b82525050565b61324d81613c73565b82525050565b61325c81613c7f565b82525050565b61327361326e82613c7f565b613d7b565b82525050565b600061328482613b25565b61328e8185613b30565b935061329e818560208601613cec565b6132a781613e43565b840191505092915050565b60006132bd82613b25565b6132c78185613b41565b93506132d7818560208601613cec565b80840191505092915050565b60006132f0601883613b30565b91506132fb82613e54565b602082019050919050565b6000613313601d83613b30565b915061331e82613e7d565b602082019050919050565b6000613336602083613b30565b915061334182613ea6565b602082019050919050565b6000613359602383613b30565b915061336482613ecf565b604082019050919050565b600061337c602283613b30565b915061338782613f1e565b604082019050919050565b600061339f602f83613b30565b91506133aa82613f6d565b604082019050919050565b60006133c2602283613b30565b91506133cd82613fbc565b604082019050919050565b60006133e5600283613b41565b91506133f08261400b565b600282019050919050565b6000613408601d83613b30565b915061341382614034565b602082019050919050565b600061342b602683613b30565b91506134368261405d565b604082019050919050565b600061344e602283613b30565b9150613459826140ac565b604082019050919050565b6000613471602283613b30565b915061347c826140fb565b604082019050919050565b6000613494601e83613b30565b915061349f8261414a565b602082019050919050565b60006134b7602883613b30565b91506134c282614173565b604082019050919050565b60006134da602483613b30565b91506134e5826141c2565b604082019050919050565b60006134fd602183613b30565b915061350882614211565b604082019050919050565b6000613520602583613b30565b915061352b82614260565b604082019050919050565b6000613543602483613b30565b915061354e826142af565b604082019050919050565b6000613566601683613b30565b9150613571826142fe565b602082019050919050565b6000613589601783613b41565b915061359482614327565b601782019050919050565b60006135ac602583613b30565b91506135b782614350565b604082019050919050565b60006135cf601183613b41565b91506135da8261439f565b601182019050919050565b60006135f2602f83613b30565b91506135fd826143c8565b604082019050919050565b6000613615601f83613b30565b915061362082614417565b602082019050919050565b61363481613cd5565b82525050565b61364381613cdf565b82525050565b6000613654826133d8565b91506136608285613262565b6020820191506136708284613262565b6020820191508190509392505050565b600061368b8261357c565b915061369782856132b2565b91506136a2826135c2565b91506136ae82846132b2565b91508190509392505050565b60006020820190506136cf6000830184613235565b92915050565b60006040820190506136ea6000830185613235565b6136f7602083018461362b565b9392505050565b60006020820190506137136000830184613244565b92915050565b600060208201905061372e6000830184613253565b92915050565b600060c0820190506137496000830189613253565b6137566020830188613235565b6137636040830187613235565b613770606083018661362b565b61377d608083018561362b565b61378a60a083018461362b565b979650505050505050565b600060a0820190506137aa6000830188613253565b6137b76020830187613253565b6137c46040830186613253565b6137d1606083018561362b565b6137de6080830184613235565b9695505050505050565b60006080820190506137fd6000830187613253565b61380a602083018661363a565b6138176040830185613253565b6138246060830184613253565b95945050505050565b600060208201905081810360008301526138478184613279565b905092915050565b60006020820190508181036000830152613868816132e3565b9050919050565b6000602082019050818103600083015261388881613306565b9050919050565b600060208201905081810360008301526138a881613329565b9050919050565b600060208201905081810360008301526138c88161334c565b9050919050565b600060208201905081810360008301526138e88161336f565b9050919050565b6000602082019050818103600083015261390881613392565b9050919050565b60006020820190508181036000830152613928816133b5565b9050919050565b60006020820190508181036000830152613948816133fb565b9050919050565b600060208201905081810360008301526139688161341e565b9050919050565b6000602082019050818103600083015261398881613441565b9050919050565b600060208201905081810360008301526139a881613464565b9050919050565b600060208201905081810360008301526139c881613487565b9050919050565b600060208201905081810360008301526139e8816134aa565b9050919050565b60006020820190508181036000830152613a08816134cd565b9050919050565b60006020820190508181036000830152613a28816134f0565b9050919050565b60006020820190508181036000830152613a4881613513565b9050919050565b60006020820190508181036000830152613a6881613536565b9050919050565b60006020820190508181036000830152613a8881613559565b9050919050565b60006020820190508181036000830152613aa88161359f565b9050919050565b60006020820190508181036000830152613ac8816135e5565b9050919050565b60006020820190508181036000830152613ae881613608565b9050919050565b6000602082019050613b04600083018461362b565b92915050565b6000602082019050613b1f600083018461363a565b92915050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b6000613b5782613cd5565b9150613b6283613cd5565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613b9757613b96613db6565b5b828201905092915050565b6000613bad82613cd5565b9150613bb883613cd5565b925082613bc857613bc7613de5565b5b828204905092915050565b6000613bde82613cd5565b9150613be983613cd5565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c2257613c21613db6565b5b828202905092915050565b6000613c3882613cd5565b9150613c4383613cd5565b925082821015613c5657613c55613db6565b5b828203905092915050565b6000613c6c82613cb5565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b60005b83811015613d0a578082015181840152602081019050613cef565b83811115613d19576000848401525b50505050565b6000613d2a82613cd5565b91506000821415613d3e57613d3d613db6565b5b600182039050919050565b60006002820490506001821680613d6157607f821691505b60208210811415613d7557613d74613e14565b5b50919050565b6000819050919050565b6000613d9082613cd5565b9150613d9b83613cd5565b925082613dab57613daa613de5565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000601f19601f8301169050919050565b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b7f4552433230536e617073686f743a206e6f6e6578697374656e74206964000000600082015250565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60008201527f6365000000000000000000000000000000000000000000000000000000000000602082015250565b7f416464726573732063616e206e6f742062652074686520746f6b656e20636f6e60008201527f7472616374277320616464726573730000000000000000000000000000000000602082015250565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b7f1901000000000000000000000000000000000000000000000000000000000000600082015250565b7f45524332305065726d69743a206578706972656420646561646c696e65000000600082015250565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b7f45524332305065726d69743a20696e76616c6964207369676e61747572650000600082015250565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206160008201527f6c6c6f77616e6365000000000000000000000000000000000000000000000000602082015250565b7f45524332303a206275726e20616d6f756e74206578636565647320616c6c6f7760008201527f616e636500000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f4552433230536e617073686f743a206964206973203000000000000000000000600082015250565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b61444981613c61565b811461445457600080fd5b50565b61446081613c73565b811461446b57600080fd5b50565b61447781613c7f565b811461448257600080fd5b50565b61448e81613c89565b811461449957600080fd5b50565b6144a581613cd5565b81146144b057600080fd5b50565b6144bc81613cdf565b81146144c757600080fd5b5056fea2646970667358221220071f89ff3064112d54b4fe2235b1b64ea9c11f2b60066a3491f6bf6ed2e12ddf64736f6c6343000804003300000000000000000000000096c2770900f4d0dd76819eca77cb3b40e119bdce00000000000000000000000056edbf72e30032d071bd09166984ccc74780334e000000000000000000000000a6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061021c5760003560e01c806379cc679011610125578063a3b0b5a3116100ad578063cf2c52cb1161007c578063cf2c52cb1461069d578063d505accf146106b9578063d5391393146106d5578063d547741f146106f3578063dd62ed3e1461070f5761021c565b8063a3b0b5a3146105ef578063a457c2d71461060d578063a9059cbb1461063d578063ca15c8731461066d5761021c565b806395d89b41116100f457806395d89b411461055b5780639711715a14610579578063981b24d0146105835780639e17a433146105b3578063a217fddf146105d15761021c565b806379cc6790146104af5780637ecebe00146104cb5780639010d07c146104fb57806391d148541461052b5761021c565b80633644e515116101a857806342966c681161017757806342966c68146103f95780634ee2cd7e146104155780635b6f547e146104455780637028e2cd1461046157806370a082311461047f5761021c565b80633644e5151461037357806336568abe1461039157806339509351146103ad57806340c10f19146103dd5761021c565b806323b872dd116101ef57806323b872dd146102bd578063248a9ca3146102ed5780632e1a7d4d1461031d5780632f2ff15d14610339578063313ce567146103555761021c565b806301ffc9a71461022157806306fdde0314610251578063095ea7b31461026f57806318160ddd1461029f575b600080fd5b61023b600480360381019061023691906131e3565b61073f565b60405161024891906136fe565b60405180910390f35b6102596107b9565b604051610266919061382d565b60405180910390f35b610289600480360381019061028491906130dd565b61084b565b60405161029691906136fe565b60405180910390f35b6102a7610869565b6040516102b49190613aef565b60405180910390f35b6102d760048036038101906102d29190612f98565b610873565b6040516102e491906136fe565b60405180910390f35b61030760048036038101906103029190613142565b6108fa565b6040516103149190613719565b60405180910390f35b6103376004803603810190610332919061320c565b610919565b005b610353600480360381019061034e919061316b565b610946565b005b61035d61097a565b60405161036a9190613b0a565b60405180910390f35b61037b610983565b6040516103889190613719565b60405180910390f35b6103ab60048036038101906103a6919061316b565b610992565b005b6103c760048036038101906103c291906130dd565b6109c6565b6040516103d491906136fe565b60405180910390f35b6103f760048036038101906103f291906130dd565b610a72565b005b610413600480360381019061040e919061320c565b610ab3565b005b61042f600480360381019061042a91906130dd565b610ac7565b60405161043c9190613aef565b60405180910390f35b61045f600480360381019061045a9190612f98565b610b37565b005b610469610be0565b6040516104769190613719565b60405180910390f35b61049960048036038101906104949190612f33565b610c04565b6040516104a69190613aef565b60405180910390f35b6104c960048036038101906104c491906130dd565b610c4d565b005b6104e560048036038101906104e09190612f33565b610cc8565b6040516104f29190613aef565b60405180910390f35b610515600480360381019061051091906131a7565b610d18565b60405161052291906136ba565b60405180910390f35b6105456004803603810190610540919061316b565b610d47565b60405161055291906136fe565b60405180910390f35b610563610db1565b604051610570919061382d565b60405180910390f35b610581610e43565b005b61059d6004803603810190610598919061320c565b610e81565b6040516105aa9190613aef565b60405180910390f35b6105bb610eb2565b6040516105c89190613aef565b60405180910390f35b6105d9610ebc565b6040516105e69190613719565b60405180910390f35b6105f7610ec3565b6040516106049190613719565b60405180910390f35b610627600480360381019061062291906130dd565b610ee7565b60405161063491906136fe565b60405180910390f35b610657600480360381019061065291906130dd565b610fd2565b60405161066491906136fe565b60405180910390f35b61068760048036038101906106829190613142565b611057565b6040516106949190613aef565b60405180910390f35b6106b760048036038101906106b29190613085565b61107b565b005b6106d360048036038101906106ce9190612fe7565b6110ea565b005b6106dd61122c565b6040516106ea9190613719565b60405180910390f35b61070d6004803603810190610708919061316b565b611250565b005b61072960048036038101906107249190612f5c565b611284565b6040516107369190613aef565b60405180910390f35b60007f5a05180f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107b257506107b182611349565b5b9050919050565b6060600580546107c890613d49565b80601f01602080910402602001604051908101604052809291908181526020018280546107f490613d49565b80156108415780601f1061081657610100808354040283529160200191610841565b820191906000526020600020905b81548152906001019060200180831161082457829003601f168201915b5050505050905090565b600061085f6108586113c3565b84846113cb565b6001905092915050565b6000600454905090565b6000823073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156108e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108dc906138ef565b60405180910390fd5b6108f0858585611596565b9150509392505050565b6000806000838152602001908152602001600020600101549050919050565b80600c600082825461092b9190613b4c565b9250508190555061094361093d6113c3565b8261168e565b50565b6109508282611867565b610975816001600085815260200190815260200160002061131990919063ffffffff16565b505050565b60006012905090565b600061098d611890565b905090565b61099c8282611953565b6109c181600160008581526020019081526020016000206119d690919063ffffffff16565b505050565b6000610a686109d36113c3565b8484600360006109e16113c3565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610a639190613b4c565b6113cb565b6001905092915050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610aa481610a9f6113c3565b611a06565b610aae8383611aa3565b505050565b610ac4610abe6113c3565b8261168e565b50565b6000806000610b1484600760008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611c04565b9150915081610b2b57610b2685610c04565b610b2d565b805b9250505092915050565b6000801b610b4c81610b476113c3565b611a06565b8373ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b8152600401610b879291906136d5565b602060405180830381600087803b158015610ba157600080fd5b505af1158015610bb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd99190613119565b5050505050565b7f5fdbd35e8da83ee755d5e62a539e5ed7f47126abede0b8b10f9ea43dc6eed07f81565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000610c6083610c5b6113c3565b611284565b905081811015610ca5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c9c906139ef565b60405180910390fd5b610cb983610cb16113c3565b8484036113cb565b610cc3838361168e565b505050565b6000610d11600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d20565b9050919050565b6000610d3f8260016000868152602001908152602001600020611d2e90919063ffffffff16565b905092915050565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b606060068054610dc090613d49565b80601f0160208091040260200160405190810160405280929190818152602001828054610dec90613d49565b8015610e395780601f10610e0e57610100808354040283529160200191610e39565b820191906000526020600020905b815481529060010190602001808311610e1c57829003601f168201915b5050505050905090565b7f5fdbd35e8da83ee755d5e62a539e5ed7f47126abede0b8b10f9ea43dc6eed07f610e7581610e706113c3565b611a06565b610e7d611d48565b5050565b6000806000610e91846008611c04565b9150915081610ea757610ea2610869565b610ea9565b805b92505050919050565b6000600c54905090565b6000801b81565b7f8f4f2da22e8ac8f11e15f9fc141cddbb5deea8800186560abb6e68c5496619a981565b60008060036000610ef66113c3565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082811015610fb3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610faa90613a8f565b60405180910390fd5b610fc7610fbe6113c3565b858584036113cb565b600191505092915050565b6000823073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611044576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161103b906138ef565b60405180910390fd5b61104e8484611d9e565b91505092915050565b600061107460016000848152602001908152602001600020611dbc565b9050919050565b7f8f4f2da22e8ac8f11e15f9fc141cddbb5deea8800186560abb6e68c5496619a96110ad816110a86113c3565b611a06565b600083838101906110be919061320c565b905080600c60008282546110d29190613c2d565b925050819055506110e38582611aa3565b5050505050565b8342111561112d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111249061392f565b60405180910390fd5b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861115c8c611dd1565b8960405160200161117296959493929190613734565b604051602081830303815290604052805190602001209050600061119582611e2f565b905060006111a582878787611e49565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611215576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120c906139af565b60405180910390fd5b6112208a8a8a6113cb565b50505050505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b61125a8282611fd4565b61127f81600160008581526020019081526020016000206119d690919063ffffffff16565b505050565b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6113158282611ffd565b5050565b6000611341836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6120dd565b905092915050565b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806113bc57506113bb8261214d565b5b9050919050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561143b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161143290613a4f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156114ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114a29061390f565b60405180910390fd5b80600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040516115899190613aef565b60405180910390a3505050565b60006115a38484846121b7565b6000600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006115ee6113c3565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508281101561166e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611665906139cf565b60405180910390fd5b6116828561167a6113c3565b8584036113cb565b60019150509392505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156116fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116f590613a0f565b60405180910390fd5b61170a8260008361243b565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015611791576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611788906138cf565b60405180910390fd5b818103600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081600460008282546117e99190613c2d565b92505081905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161184e9190613aef565b60405180910390a36118628360008461244b565b505050565b611870826108fa565b6118818161187c6113c3565b611a06565b61188b8383611ffd565b505050565b60007f00000000000000000000000000000000000000000000000000000000000000894614156118e2577f3539c5bc9c7ebcf234751d97f39159295f282f8ca369c03b02b3c06701ff28ea9050611950565b61194d7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f8373a9c44638cc1790be8335ded3669d92b61f525d3b08451622ab6077751f917fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6612450565b90505b90565b61195b6113c3565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146119c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119bf90613aaf565b60405180910390fd5b6119d2828261248a565b5050565b60006119fe836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61256b565b905092915050565b611a108282610d47565b611a9f57611a358173ffffffffffffffffffffffffffffffffffffffff1660146126f1565b611a438360001c60206126f1565b604051602001611a54929190613680565b6040516020818303038152906040526040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a96919061382d565b60405180910390fd5b5050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611b13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b0a90613acf565b60405180910390fd5b611b1f6000838361243b565b8060046000828254611b319190613b4c565b9250508190555080600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611b879190613b4c565b925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611bec9190613aef565b60405180910390a3611c006000838361244b565b5050565b60008060008411611c4a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c4190613a6f565b60405180910390fd5b611c526129eb565b841115611c94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8b9061386f565b60405180910390fd5b6000611cac85856000016129fc90919063ffffffff16565b90508360000180549050811415611cca576000809250925050611d19565b6001846001018281548110611d08577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015492509250505b9250929050565b600081600001549050919050565b6000611d3d8360000183612b22565b60001c905092915050565b6000611d54600a612b73565b6000611d5e6129eb565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb6781604051611d8f9190613aef565b60405180910390a18091505090565b6000611db2611dab6113c3565b84846121b7565b6001905092915050565b6000611dca82600001612b89565b9050919050565b600080600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050611e1e81611d20565b9150611e2981612b73565b50919050565b6000611e42611e3c611890565b83612b9a565b9050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08260001c1115611eb1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea89061396f565b60405180910390fd5b601b8460ff161480611ec65750601c8460ff16145b611f05576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611efc9061398f565b60405180910390fd5b600060018686868660405160008152602001604052604051611f2a94939291906137e8565b6020604051602081039080840390855afa158015611f4c573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611fc8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fbf9061384f565b60405180910390fd5b80915050949350505050565b611fdd826108fa565b611fee81611fe96113c3565b611a06565b611ff8838361248a565b505050565b6120078282610d47565b6120d957600160008084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555061207e6113c3565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60006120e98383612bcd565b612142578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050612147565b600090505b92915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612227576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161221e90613a2f565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612297576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161228e906138af565b60405180910390fd5b6122a283838361243b565b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015612329576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123209061394f565b60405180910390fd5b818103600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546123be9190613b4c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516124229190613aef565b60405180910390a361243584848461244b565b50505050565b612446838383612bf0565b505050565b505050565b6000838383463060405160200161246b959493929190613795565b6040516020818303038152906040528051906020012090509392505050565b6124948282610d47565b1561256757600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555061250c6113c3565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b600080836001016000848152602001908152602001600020549050600081146126e557600060018261259d9190613c2d565b90506000600186600001805490506125b59190613c2d565b90508181146126705760008660000182815481106125fc577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905080876000018481548110612646577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b856000018054806126aa577f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506126eb565b60009150505b92915050565b6060600060028360026127049190613bd3565b61270e9190613b4c565b67ffffffffffffffff81111561274d577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561277f5781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106127dd577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110612867577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026128a79190613bd3565b6128b19190613b4c565b90505b600181111561299d577f3031323334353637383961626364656600000000000000000000000000000000600f861660108110612919577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b1a60f81b828281518110612956577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c94508061299690613d1f565b90506128b4565b50600084146129e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129d89061388f565b60405180910390fd5b8091505092915050565b60006129f7600a611d20565b905090565b60008083805490501415612a135760009050612b1c565b600080848054905090505b80821015612a9d576000612a328383612caa565b905084868281548110612a6e577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001541115612a8757809150612a97565b600181612a949190613b4c565b92505b50612a1e565b600082118015612afb57508385600184612ab79190613c2d565b81548110612aee577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154145b15612b1657600182612b0d9190613c2d565b92505050612b1c565b81925050505b92915050565b6000826000018281548110612b60577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905092915050565b6001816000016000828254019250508190555050565b600081600001805490509050919050565b60008282604051602001612baf929190613649565b60405160208183030381529060405280519060200120905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b612bfb838383612d11565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612c4657612c3982612d16565b612c41612d69565b612ca5565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612c9157612c8483612d16565b612c8c612d69565b612ca4565b612c9a83612d16565b612ca382612d16565b5b5b505050565b600060028083612cba9190613d85565b600285612cc79190613d85565b612cd19190613b4c565b612cdb9190613ba2565b600283612ce89190613ba2565b600285612cf59190613ba2565b612cff9190613b4c565b612d099190613b4c565b905092915050565b505050565b612d66600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612d6183610c04565b612d7d565b50565b612d7b6008612d76610869565b612d7d565b565b6000612d876129eb565b905080612d9684600001612df8565b1015612df35782600001819080600181540180825580915050600190039060005260206000200160009091909190915055826001018290806001815401808255809150506001900390600052602060002001600090919091909150555b505050565b60008082805490501415612e0f5760009050612e66565b8160018380549050612e219190613c2d565b81548110612e58577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015490505b919050565b600081359050612e7a81614440565b92915050565b600081519050612e8f81614457565b92915050565b600081359050612ea48161446e565b92915050565b600081359050612eb981614485565b92915050565b60008083601f840112612ed157600080fd5b8235905067ffffffffffffffff811115612eea57600080fd5b602083019150836001820283011115612f0257600080fd5b9250929050565b600081359050612f188161449c565b92915050565b600081359050612f2d816144b3565b92915050565b600060208284031215612f4557600080fd5b6000612f5384828501612e6b565b91505092915050565b60008060408385031215612f6f57600080fd5b6000612f7d85828601612e6b565b9250506020612f8e85828601612e6b565b9150509250929050565b600080600060608486031215612fad57600080fd5b6000612fbb86828701612e6b565b9350506020612fcc86828701612e6b565b9250506040612fdd86828701612f09565b9150509250925092565b600080600080600080600060e0888a03121561300257600080fd5b60006130108a828b01612e6b565b97505060206130218a828b01612e6b565b96505060406130328a828b01612f09565b95505060606130438a828b01612f09565b94505060806130548a828b01612f1e565b93505060a06130658a828b01612e95565b92505060c06130768a828b01612e95565b91505092959891949750929550565b60008060006040848603121561309a57600080fd5b60006130a886828701612e6b565b935050602084013567ffffffffffffffff8111156130c557600080fd5b6130d186828701612ebf565b92509250509250925092565b600080604083850312156130f057600080fd5b60006130fe85828601612e6b565b925050602061310f85828601612f09565b9150509250929050565b60006020828403121561312b57600080fd5b600061313984828501612e80565b91505092915050565b60006020828403121561315457600080fd5b600061316284828501612e95565b91505092915050565b6000806040838503121561317e57600080fd5b600061318c85828601612e95565b925050602061319d85828601612e6b565b9150509250929050565b600080604083850312156131ba57600080fd5b60006131c885828601612e95565b92505060206131d985828601612f09565b9150509250929050565b6000602082840312156131f557600080fd5b600061320384828501612eaa565b91505092915050565b60006020828403121561321e57600080fd5b600061322c84828501612f09565b91505092915050565b61323e81613c61565b82525050565b61324d81613c73565b82525050565b61325c81613c7f565b82525050565b61327361326e82613c7f565b613d7b565b82525050565b600061328482613b25565b61328e8185613b30565b935061329e818560208601613cec565b6132a781613e43565b840191505092915050565b60006132bd82613b25565b6132c78185613b41565b93506132d7818560208601613cec565b80840191505092915050565b60006132f0601883613b30565b91506132fb82613e54565b602082019050919050565b6000613313601d83613b30565b915061331e82613e7d565b602082019050919050565b6000613336602083613b30565b915061334182613ea6565b602082019050919050565b6000613359602383613b30565b915061336482613ecf565b604082019050919050565b600061337c602283613b30565b915061338782613f1e565b604082019050919050565b600061339f602f83613b30565b91506133aa82613f6d565b604082019050919050565b60006133c2602283613b30565b91506133cd82613fbc565b604082019050919050565b60006133e5600283613b41565b91506133f08261400b565b600282019050919050565b6000613408601d83613b30565b915061341382614034565b602082019050919050565b600061342b602683613b30565b91506134368261405d565b604082019050919050565b600061344e602283613b30565b9150613459826140ac565b604082019050919050565b6000613471602283613b30565b915061347c826140fb565b604082019050919050565b6000613494601e83613b30565b915061349f8261414a565b602082019050919050565b60006134b7602883613b30565b91506134c282614173565b604082019050919050565b60006134da602483613b30565b91506134e5826141c2565b604082019050919050565b60006134fd602183613b30565b915061350882614211565b604082019050919050565b6000613520602583613b30565b915061352b82614260565b604082019050919050565b6000613543602483613b30565b915061354e826142af565b604082019050919050565b6000613566601683613b30565b9150613571826142fe565b602082019050919050565b6000613589601783613b41565b915061359482614327565b601782019050919050565b60006135ac602583613b30565b91506135b782614350565b604082019050919050565b60006135cf601183613b41565b91506135da8261439f565b601182019050919050565b60006135f2602f83613b30565b91506135fd826143c8565b604082019050919050565b6000613615601f83613b30565b915061362082614417565b602082019050919050565b61363481613cd5565b82525050565b61364381613cdf565b82525050565b6000613654826133d8565b91506136608285613262565b6020820191506136708284613262565b6020820191508190509392505050565b600061368b8261357c565b915061369782856132b2565b91506136a2826135c2565b91506136ae82846132b2565b91508190509392505050565b60006020820190506136cf6000830184613235565b92915050565b60006040820190506136ea6000830185613235565b6136f7602083018461362b565b9392505050565b60006020820190506137136000830184613244565b92915050565b600060208201905061372e6000830184613253565b92915050565b600060c0820190506137496000830189613253565b6137566020830188613235565b6137636040830187613235565b613770606083018661362b565b61377d608083018561362b565b61378a60a083018461362b565b979650505050505050565b600060a0820190506137aa6000830188613253565b6137b76020830187613253565b6137c46040830186613253565b6137d1606083018561362b565b6137de6080830184613235565b9695505050505050565b60006080820190506137fd6000830187613253565b61380a602083018661363a565b6138176040830185613253565b6138246060830184613253565b95945050505050565b600060208201905081810360008301526138478184613279565b905092915050565b60006020820190508181036000830152613868816132e3565b9050919050565b6000602082019050818103600083015261388881613306565b9050919050565b600060208201905081810360008301526138a881613329565b9050919050565b600060208201905081810360008301526138c88161334c565b9050919050565b600060208201905081810360008301526138e88161336f565b9050919050565b6000602082019050818103600083015261390881613392565b9050919050565b60006020820190508181036000830152613928816133b5565b9050919050565b60006020820190508181036000830152613948816133fb565b9050919050565b600060208201905081810360008301526139688161341e565b9050919050565b6000602082019050818103600083015261398881613441565b9050919050565b600060208201905081810360008301526139a881613464565b9050919050565b600060208201905081810360008301526139c881613487565b9050919050565b600060208201905081810360008301526139e8816134aa565b9050919050565b60006020820190508181036000830152613a08816134cd565b9050919050565b60006020820190508181036000830152613a28816134f0565b9050919050565b60006020820190508181036000830152613a4881613513565b9050919050565b60006020820190508181036000830152613a6881613536565b9050919050565b60006020820190508181036000830152613a8881613559565b9050919050565b60006020820190508181036000830152613aa88161359f565b9050919050565b60006020820190508181036000830152613ac8816135e5565b9050919050565b60006020820190508181036000830152613ae881613608565b9050919050565b6000602082019050613b04600083018461362b565b92915050565b6000602082019050613b1f600083018461363a565b92915050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b6000613b5782613cd5565b9150613b6283613cd5565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613b9757613b96613db6565b5b828201905092915050565b6000613bad82613cd5565b9150613bb883613cd5565b925082613bc857613bc7613de5565b5b828204905092915050565b6000613bde82613cd5565b9150613be983613cd5565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c2257613c21613db6565b5b828202905092915050565b6000613c3882613cd5565b9150613c4383613cd5565b925082821015613c5657613c55613db6565b5b828203905092915050565b6000613c6c82613cb5565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b60005b83811015613d0a578082015181840152602081019050613cef565b83811115613d19576000848401525b50505050565b6000613d2a82613cd5565b91506000821415613d3e57613d3d613db6565b5b600182039050919050565b60006002820490506001821680613d6157607f821691505b60208210811415613d7557613d74613e14565b5b50919050565b6000819050919050565b6000613d9082613cd5565b9150613d9b83613cd5565b925082613dab57613daa613de5565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000601f19601f8301169050919050565b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b7f4552433230536e617073686f743a206e6f6e6578697374656e74206964000000600082015250565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60008201527f6365000000000000000000000000000000000000000000000000000000000000602082015250565b7f416464726573732063616e206e6f742062652074686520746f6b656e20636f6e60008201527f7472616374277320616464726573730000000000000000000000000000000000602082015250565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b7f1901000000000000000000000000000000000000000000000000000000000000600082015250565b7f45524332305065726d69743a206578706972656420646561646c696e65000000600082015250565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b7f45524332305065726d69743a20696e76616c6964207369676e61747572650000600082015250565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206160008201527f6c6c6f77616e6365000000000000000000000000000000000000000000000000602082015250565b7f45524332303a206275726e20616d6f756e74206578636565647320616c6c6f7760008201527f616e636500000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f4552433230536e617073686f743a206964206973203000000000000000000000600082015250565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b61444981613c61565b811461445457600080fd5b50565b61446081613c73565b811461446b57600080fd5b50565b61447781613c7f565b811461448257600080fd5b50565b61448e81613c89565b811461449957600080fd5b50565b6144a581613cd5565b81146144b057600080fd5b50565b6144bc81613cdf565b81146144c757600080fd5b5056fea2646970667358221220071f89ff3064112d54b4fe2235b1b64ea9c11f2b60066a3491f6bf6ed2e12ddf64736f6c63430008040033

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

00000000000000000000000096c2770900f4d0dd76819eca77cb3b40e119bdce00000000000000000000000056edbf72e30032d071bd09166984ccc74780334e000000000000000000000000a6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa

-----Decoded View---------------
Arg [0] : defaultAdmin (address): 0x96C2770900f4D0Dd76819eca77cB3b40e119BdCe
Arg [1] : minter (address): 0x56EdBf72E30032D071bd09166984cCc74780334E
Arg [2] : childChainManager (address): 0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000096c2770900f4d0dd76819eca77cb3b40e119bdce
Arg [1] : 00000000000000000000000056edbf72e30032d071bd09166984ccc74780334e
Arg [2] : 000000000000000000000000a6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa


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.