Polygon Sponsored slots available. Book your slot here!
ERC-20
FxChild
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)
Balance
165,992,366.411297335772745729 DLYCOPValue
$682.23 ( ~1,062.9516 POL) [0.0115%]Loading...
Loading
Loading...
Loading
Loading...
Loading
Contract Name:
DailyCopTokenChild
Compiler Version
v0.8.4+commit.c7e474f2
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
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
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.