Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
PirateApes
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';
import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol';
import './ERC721Upgradeable.sol';
/***
*
* ##### ##
* ###### /### #
* /# / / ### ### #
* / / / ### # ##
* / / ## ##
* ## ## ## ### ### /### /### ######## /##
* ## ## ## ### ###/ #### / / ### / ######## / ###
* /### ## / ## ## ###/ / ###/ ## / ###
* / ### ## / ## ## ## ## ## ## ###
* ## ######/ ## ## ## ## ## ########
* ## ###### ## ## ## ## ## #######
* ## ## ## ## ## ## ## ##
* ## ## ## ## ## /# ## #### /
* ## ## ### / ### ####/ ## ## ######/
* ## ## ## ##/ ### ### ## ## #####
* ### # /
* ### /
* #####/
* ###
*
* ##
* /####
* / ###
* /##
* / ##
* / ## /### /## /###
* / ## / ### / / ### / #### /
* / ## / ###/ / ### ## ###/
* / ## ## ## ## ### ####
* /######## ## ## ######## ###
* / ## ## ## ####### ###
* # ## ## ## ## ###
* /#### ## ## ## #### / /### ##
* / #### ## / ####### ######/ / #### /
* / ## #/ ###### ##### ###/
* # ##
* ## ##
* ##
* ##
*/
contract PirateApes is OwnableUpgradeable, ERC721Upgradeable {
uint256 public constant MAX_SUPPLY = 5700;
uint16 public constant MAX_TOTAL_BATCH_SIZE = 10;
uint8 public constant LOCATION_HEAVEN = 255;
uint8 public constant LOCATION_QUARANTINE = 254;
uint16 public constant FREE_AMOUNT_OG = 3;
uint16 public constant FREE_AMOUNT_WL = 2;
uint16 public constant FREE_AMOUNT_PUBLIC = 1;
uint256 public constant PRICE_1_EXTRA = 0.04 ether;
uint256 public constant PRICE_4_EXTRA = 0.14 ether;
uint256 public constant PRICE_7_EXTRA = 0.21 ether;
uint256 public SALE_STARTED_AT_OG;
uint256 public SALE_STARTED_AT_WL;
uint256 public SALE_STARTED_AT_PUBLIC;
uint256 public supply;
uint256 public burned;
address private _proxyRegistryAddress;
address private _verifier;
string private _baseTokenURI;
struct TokenMeta {
address owner;
uint16 batch;
uint8 locationId;
uint72 meta;
}
mapping(uint256 => TokenMeta) public tokenState;
struct TokenOwnerState {
uint16 startTokenId;
uint16 batch;
uint16 balance;
uint208 meta;
}
mapping(address => TokenOwnerState) public tokenOwnerState;
mapping(address => bool) private _operators;
mapping(uint256 => address) public _minters;
event Locked(
address indexed ownder,
address indexed locker,
bool indexed state
);
struct Lock {
address locker;
uint96 meta;
}
mapping(address => Lock) public locked;
mapping(address => bool) public markets;
function initialize(address verifier_, address proxyRegistryAddress_)
public
initializer
{
__ERC721_init('PirateApes', 'BAPC');
__Ownable_init();
_verifier = verifier_;
_proxyRegistryAddress = proxyRegistryAddress_;
_operators[_msgSender()] = true;
}
/**
* This is used instead of msg.sender as transactions won't be sent by the original token owner, but by OpenSea.
*/
function _msgSender() internal view override returns (address sender) {
if (msg.sender == address(this)) {
bytes memory array = msg.data;
uint256 index = msg.data.length;
assembly {
// Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
sender := and(
mload(add(array, index)),
0xffffffffffffffffffffffffffffffffffffffff
)
}
} else {
sender = msg.sender;
}
return sender;
}
function actualOwnerOf(uint256 tokenId) public view returns (address) {
require(_exists(tokenId), 'ERC721: token does not exist');
if (tokenState[tokenId].owner != address(0)) {
return tokenState[tokenId].owner;
}
return _minters[tokenId];
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner_)
public
view
virtual
override
returns (uint256)
{
require(owner_ != address(0), 'ERC721: balance query for the zero address');
return tokenOwnerState[owner_].balance;
}
function ownerOf(uint256 tokenId)
public
view
virtual
override
returns (address)
{
return actualOwnerOf(tokenId);
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId)
internal
view
virtual
override
returns (bool)
{
return tokenId <= supply;
}
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
require(
(locked[from].locker == address(0)) ||
markets[_msgSender()] ||
// workaround, when "transfer" to the contract wallet is used to estimate gas (eg x2y2)
(to == 0x3B9edBC42bA4ACEDb4f2Aa290aEFBb40cd10fCAc),
'BAPC: owner is locked for transfers'
);
_transferFrom(from, to, tokenId);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transferFrom(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ownerOf(tokenId) == from, 'ERC721: transfer from incorrect owner');
require(to != address(0), 'ERC721: transfer to the zero address');
require(to != from, "ERC721: can't transfer themself");
require(
tokenState[tokenId].locationId == 0,
"BAPC: token can't be transferred"
);
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
tokenOwnerState[from].balance -= 1;
tokenOwnerState[to].balance += 1;
tokenState[tokenId].owner = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
function _recoverSigner(bytes32 hash, bytes memory signature)
internal
pure
returns (address)
{
return
ECDSAUpgradeable.recover(
ECDSAUpgradeable.toEthSignedMessageHash(hash),
signature
);
}
function _baseURI() internal view virtual override returns (string memory) {
return _baseTokenURI;
}
/**
* Override isApprovedForAll to whitelist user's OpenSea proxy accounts to enable gas-less listings.
*/
function isApprovedForAll(address owner_, address operator_)
public
view
override
returns (bool)
{
// Whitelist OpenSea proxy contract for easy trading.
ProxyRegistry proxyRegistry = ProxyRegistry(_proxyRegistryAddress);
if (address(proxyRegistry.proxies(owner_)) == operator_) {
return true;
}
return super.isApprovedForAll(owner_, operator_);
}
function _lock(address locker) internal {
address wallet = _msgSender();
require(locked[wallet].locker == address(0), 'BAPC: already locked');
locked[wallet].locker = locker;
emit Locked(wallet, locker, true);
}
function _unlock(address wallet) internal {
address locker = _msgSender();
require(locked[wallet].locker == locker, 'BAPC: cant unlock this wallet');
locked[wallet].locker = address(0);
emit Locked(wallet, locker, false);
}
function lock(address locker) external {
address wallet = _msgSender();
require(wallet != locker, 'BAPC: cant lock themselves');
_lock(locker);
}
function unlock(address wallet) external {
address locker = _msgSender();
require(locker != wallet, 'BAPC: cant unlock themselves');
_unlock(wallet);
}
function lock(uint256 timestamp, bytes memory sig) external {
address wallet = _msgSender();
address locker = wallet;
bytes32 hash = keccak256(abi.encodePacked(wallet, locker, true, timestamp));
require(_verifier == _recoverSigner(hash, sig), 'BAPC: invalid signature');
_lock(locker);
}
function unlock(
address wallet,
uint256 timestamp,
bytes memory sig
) external {
address locker = _msgSender();
bytes32 hash = keccak256(
abi.encodePacked(wallet, locker, false, timestamp)
);
require(_verifier == _recoverSigner(hash, sig), 'BAPC: invalid signature');
_unlock(wallet);
}
function transfer(
address to,
uint256 tokenId,
uint256 timestamp,
bytes memory sig
) external {
address from = _msgSender();
bytes32 hash = keccak256(abi.encodePacked(from, to, tokenId, timestamp));
require(_verifier == _recoverSigner(hash, sig), 'BAPC: invalid signature');
_transferFrom(from, to, tokenId);
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return supply - burned;
}
/* onlyOwner */
modifier onlyOperator() {
require(_operators[_msgSender()] == true, 'Caller is not the operator');
_;
}
function setOperator(address operatorAddress, bool value) public onlyOwner {
_operators[operatorAddress] = value;
}
function setMarketplace(address marketAddress, bool value) public onlyOwner {
markets[marketAddress] = value;
}
function setVerifier(address verifier_) external onlyOwner {
_verifier = verifier_;
}
function setBaseURI(string memory baseURI_) external onlyOwner {
_baseTokenURI = baseURI_;
}
function withdraw(uint256 amount) public onlyOwner {
(bool success, ) = _msgSender().call{value: amount}('');
require(success, 'Withdraw failed');
}
function withdrawAll() external onlyOwner {
withdraw(address(this).balance);
}
/**
* @dev for testing only
*/
function _mint(address to, uint16 amount) external onlyOwner {
require(
amount > 0 && (supply + amount) <= MAX_SUPPLY,
'BAPC: invalid amount'
);
uint256 tokenIdFrom = supply + 1;
for (uint16 i = 0; i < amount; i++) {
uint256 tokenId = tokenIdFrom + i;
tokenState[tokenId].owner = to;
emit Transfer(address(0), to, tokenId);
}
tokenOwnerState[to].balance += amount;
supply += amount;
}
}
contract OwnableDelegateProxy {}
contract ProxyRegistry {
mapping(address => OwnableDelegateProxy) public proxies;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original
* initialization step. This is essential to configure modules that are added through upgrades and that require
* initialization.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../StringsUpgradeable.sol";
/**
* @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 ECDSAUpgradeable {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. 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]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
// 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.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(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.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
vs := mload(add(signature, 0x40))
}
return tryRecover(hash, r, vs);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @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.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} 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.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// 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 (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): 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.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @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) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @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 Message, created from `s`. 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(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", StringsUpgradeable.toString(s.length), s));
}
/**
* @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));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.0;
import '@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol';
import '@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol';
import '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721Upgradeable is
Initializable,
ContextUpgradeable,
ERC165Upgradeable,
IERC721Upgradeable,
IERC721MetadataUpgradeable
{
using AddressUpgradeable for address;
using StringsUpgradeable for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
function __ERC721_init(string memory name_, string memory symbol_)
internal
onlyInitializing
{
__Context_init_unchained();
__ERC165_init_unchained();
__ERC721_init_unchained(name_, symbol_);
}
function __ERC721_init_unchained(string memory name_, string memory symbol_)
internal
onlyInitializing
{
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override(ERC165Upgradeable, IERC165Upgradeable)
returns (bool)
{
return
interfaceId == type(IERC721Upgradeable).interfaceId ||
interfaceId == type(IERC721MetadataUpgradeable).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner)
public
view
virtual
override
returns (uint256)
{
require(false, 'Implementation required');
return 0;
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId)
public
view
virtual
override
returns (address)
{
require(false, 'Implementation required');
return address(0);
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId)
public
view
virtual
override
returns (string memory)
{
require(
_exists(tokenId),
'ERC721Metadata: URI query for nonexistent token'
);
string memory baseURI = _baseURI();
return
bytes(baseURI).length > 0
? string(abi.encodePacked(baseURI, tokenId.toString()))
: '';
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return '';
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ownerOf(tokenId);
require(to != owner, 'ERC721: approval to current owner');
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
'ERC721: approve caller is not owner nor approved for all'
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId)
public
view
virtual
override
returns (address)
{
require(
_exists(tokenId),
'ERC721: approved query for nonexistent token'
);
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved)
public
virtual
override
{
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator)
public
view
virtual
override
returns (bool)
{
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//solhint-disable-next-line max-line-length
require(
_isApprovedOrOwner(_msgSender(), tokenId),
'ERC721: transfer caller is not owner nor approved'
);
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, '');
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(
_isApprovedOrOwner(_msgSender(), tokenId),
'ERC721: transfer caller is not owner nor approved'
);
_safeTransfer(from, to, tokenId, _data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received},
* which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(
_checkOnERC721Received(from, to, tokenId, _data),
'ERC721: transfer to non ERC721Receiver implementer'
);
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
require(false, 'Implementation required');
return false;
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId)
internal
view
virtual
returns (bool)
{
require(
_exists(tokenId),
'ERC721: operator query for nonexistent token'
);
address owner = ownerOf(tokenId);
return (spender == owner ||
getApproved(tokenId) == spender ||
isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received},
* which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, '');
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
'ERC721: transfer to non ERC721Receiver implementer'
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits a {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits a {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, 'ERC721: approve to caller');
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try
IERC721ReceiverUpgradeable(to).onERC721Received(
_msgSender(),
from,
tokenId,
_data
)
returns (bytes4 retval) {
return
retval ==
IERC721ReceiverUpgradeable.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert(
'ERC721: transfer to non ERC721Receiver implementer'
);
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` 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 tokenId
) 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.
* - `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 tokenId
) internal virtual {}
uint256[44] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @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 ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library StringsUpgradeable {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165Upgradeable.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721Upgradeable is IERC165Upgradeable {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721ReceiverUpgradeable {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC721Upgradeable.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721MetadataUpgradeable is IERC721Upgradeable {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165Upgradeable.sol";
import "../../proxy/utils/Initializable.sol";
/**
* @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 ERC165Upgradeable is Initializable, IERC165Upgradeable {
function __ERC165_init() internal onlyInitializing {
}
function __ERC165_init_unchained() internal onlyInitializing {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165Upgradeable).interfaceId;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165Upgradeable {
/**
* @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);
}{
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"ownder","type":"address"},{"indexed":true,"internalType":"address","name":"locker","type":"address"},{"indexed":true,"internalType":"bool","name":"state","type":"bool"}],"name":"Locked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"FREE_AMOUNT_OG","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FREE_AMOUNT_PUBLIC","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FREE_AMOUNT_WL","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCATION_HEAVEN","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCATION_QUARANTINE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TOTAL_BATCH_SIZE","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_1_EXTRA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_4_EXTRA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_7_EXTRA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SALE_STARTED_AT_OG","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SALE_STARTED_AT_PUBLIC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SALE_STARTED_AT_WL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint16","name":"amount","type":"uint16"}],"name":"_mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"_minters","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"actualOwnerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"verifier_","type":"address"},{"internalType":"address","name":"proxyRegistryAddress_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"operator_","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"locker","type":"address"}],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"locked","outputs":[{"internalType":"address","name":"locker","type":"address"},{"internalType":"uint96","name":"meta","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"markets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI_","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"marketAddress","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setMarketplace","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"verifier_","type":"address"}],"name":"setVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenOwnerState","outputs":[{"internalType":"uint16","name":"startTokenId","type":"uint16"},{"internalType":"uint16","name":"batch","type":"uint16"},{"internalType":"uint16","name":"balance","type":"uint16"},{"internalType":"uint208","name":"meta","type":"uint208"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenState","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint16","name":"batch","type":"uint16"},{"internalType":"uint8","name":"locationId","type":"uint8"},{"internalType":"uint72","name":"meta","type":"uint72"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"unlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"unlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50615b4180620000216000396000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c80637245bd5b1161019d578063a22cb465116100e9578063cbf9fe5f116100a2578063e985e9c51161007c578063e985e9c5146108fd578063f2fde38b1461092d578063f435f5a714610949578063f9c7324114610965576102f1565b8063cbf9fe5f14610894578063d8f7c836146108c5578063dabd76e9146108e1576102f1565b8063a22cb465146107d4578063abee0803146107f0578063af8d6ad81461080c578063b88d4fde1461082a578063c87b56dd14610846578063ca6cffd114610876576102f1565b806386ccdecf116101565780638e8f294b116101305780638e8f294b1461073557806395d89b41146107655780639745cc3d146107835780639e2c0b23146107b6576102f1565b806386ccdecf146106db5780638c418eb2146106f95780638da5cb5b14610717576102f1565b80637245bd5b1461063d578063725ce2891461065b57806373f42561146106795780637419e77a14610697578063747a7761146106b3578063853828b6146106d1576102f1565b8063407b5ee61161025c57806355f804b3116102155780636db021ee116101ef5780636db021ee146105b55780636f8e76f5146105e557806370a0823114610603578063715018a614610633576102f1565b806355f804b31461054d578063597dfb98146105695780636352211e14610585576102f1565b8063407b5ee61461048c578063408b3cdb146104aa57806342842e0e146104dd578063485cc955146104f95780635437988d14610515578063558a729714610531576102f1565b8063197a089c116102ae578063197a089c146103cc57806323b872dd146103ea5780632a29ad14146104065780632e1a7d4d146104365780632f6c493c1461045257806332cb6b0c1461046e576102f1565b806301ffc9a7146102f6578063047fc9aa1461032657806306fdde0314610344578063081812fc14610362578063095ea7b31461039257806318160ddd146103ae575b600080fd5b610310600480360381019061030b919061387a565b610983565b60405161031d91906138c2565b60405180910390f35b61032e610a65565b60405161033b91906138f6565b60405180910390f35b61034c610a6b565b60405161035991906139aa565b60405180910390f35b61037c600480360381019061037791906139f8565b610afd565b6040516103899190613a66565b60405180910390f35b6103ac60048036038101906103a79190613aad565b610b82565b005b6103b6610c99565b6040516103c391906138f6565b60405180910390f35b6103d4610cb0565b6040516103e191906138f6565b60405180910390f35b61040460048036038101906103ff9190613aed565b610cb6565b005b610420600480360381019061041b91906139f8565b610d16565b60405161042d9190613a66565b60405180910390f35b610450600480360381019061044b91906139f8565b610d49565b005b61046c60048036038101906104679190613b40565b610e08565b005b610476610e8f565b60405161048391906138f6565b60405180910390f35b610494610e95565b6040516104a19190613b89565b60405180910390f35b6104c460048036038101906104bf9190613b40565b610e9a565b6040516104d49493929190613bf6565b60405180910390f35b6104f760048036038101906104f29190613aed565b610f1a565b005b610513600480360381019061050e9190613c3b565b610f3a565b005b61052f600480360381019061052a9190613b40565b6111cf565b005b61054b60048036038101906105469190613ca7565b61121b565b005b61056760048036038101906105629190613e1c565b61127e565b005b610583600480360381019061057e9190613e91565b611299565b005b61059f600480360381019061059a91906139f8565b6114a2565b6040516105ac9190613a66565b60405180910390f35b6105cf60048036038101906105ca91906139f8565b6114b4565b6040516105dc9190613a66565b60405180910390f35b6105ed6115e2565b6040516105fa9190613b89565b60405180910390f35b61061d60048036038101906106189190613b40565b6115e7565b60405161062a91906138f6565b60405180910390f35b61063b6116b3565b005b6106456116c7565b60405161065291906138f6565b60405180910390f35b6106636116d3565b6040516106709190613ed1565b60405180910390f35b6106816116d8565b60405161068e91906138f6565b60405180910390f35b6106b160048036038101906106ac9190613ca7565b6116de565b005b6106bb611741565b6040516106c891906138f6565b60405180910390f35b6106d961174d565b005b6106e3611760565b6040516106f09190613ed1565b60405180910390f35b610701611765565b60405161070e9190613ed1565b60405180910390f35b61071f61176a565b60405161072c9190613a66565b60405180910390f35b61074f600480360381019061074a9190613b40565b611794565b60405161075c91906138c2565b60405180910390f35b61076d6117b4565b60405161077a91906139aa565b60405180910390f35b61079d600480360381019061079891906139f8565b611846565b6040516107ad9493929190613f10565b60405180910390f35b6107be6118c6565b6040516107cb9190613ed1565b60405180910390f35b6107ee60048036038101906107e99190613ca7565b6118cb565b005b61080a60048036038101906108059190613ff6565b6118e1565b005b6108146119c8565b60405161082191906138f6565b60405180910390f35b610844600480360381019061083f9190614065565b6119d3565b005b610860600480360381019061085b91906139f8565b611a35565b60405161086d91906139aa565b60405180910390f35b61087e611adc565b60405161088b91906138f6565b60405180910390f35b6108ae60048036038101906108a99190613b40565b611ae2565b6040516108bc92919061410f565b60405180910390f35b6108df60048036038101906108da9190614138565b611b3e565b005b6108fb60048036038101906108f69190614194565b611c2a565b005b61091760048036038101906109129190613c3b565b611d13565b60405161092491906138c2565b60405180910390f35b61094760048036038101906109429190613b40565b611e05565b005b610963600480360381019061095e9190613b40565b611e88565b005b61096d611f0f565b60405161097a91906138f6565b60405180910390f35b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610a4e57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610a5e5750610a5d82611f15565b5b9050919050565b60ca5481565b606060978054610a7a90614246565b80601f0160208091040260200160405190810160405280929190818152602001828054610aa690614246565b8015610af35780601f10610ac857610100808354040283529160200191610af3565b820191906000526020600020905b815481529060010190602001808311610ad657829003601f168201915b5050505050905090565b6000610b0882611f7f565b610b47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3e906142e9565b60405180910390fd5b6099600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610b8d826114a2565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610bfd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf49061437b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610c1c611f8e565b73ffffffffffffffffffffffffffffffffffffffff161480610c4b5750610c4a81610c45611f8e565b611d13565b5b610c8a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c819061440d565b60405180910390fd5b610c94838361203e565b505050565b600060cb5460ca54610cab919061445c565b905090565b60c95481565b610cc7610cc1611f8e565b826120f7565b610d06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cfd90614502565b60405180910390fd5b610d118383836121d5565b505050565b60d26020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610d5161235b565b6000610d5b611f8e565b73ffffffffffffffffffffffffffffffffffffffff1682604051610d7e90614553565b60006040518083038185875af1925050503d8060008114610dbb576040519150601f19603f3d011682016040523d82523d6000602084013e610dc0565b606091505b5050905080610e04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfb906145b4565b60405180910390fd5b5050565b6000610e12611f8e565b90508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610e82576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7990614620565b60405180910390fd5b610e8b826123d9565b5050565b61164481565b60fe81565b60d06020528060005260406000206000915090508060000160009054906101000a900461ffff16908060000160029054906101000a900461ffff16908060000160049054906101000a900461ffff16908060000160069054906101000a900479ffffffffffffffffffffffffffffffffffffffffffffffffffff16905084565b610f35838383604051806020016040528060008152506119d3565b505050565b60008060019054906101000a900460ff16159050808015610f6b5750600160008054906101000a900460ff1660ff16105b80610f985750610f7a30612599565b158015610f975750600160008054906101000a900460ff1660ff16145b5b610fd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fce906146b2565b60405180910390fd5b60016000806101000a81548160ff021916908360ff1602179055508015611014576001600060016101000a81548160ff0219169083151502179055505b6110886040518060400160405280600a81526020017f50697261746541706573000000000000000000000000000000000000000000008152506040518060400160405280600481526020017f42415043000000000000000000000000000000000000000000000000000000008152506125bc565b611090612629565b8260cd60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160cc60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160d16000611120611f8e565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555080156111ca5760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860016040516111c19190614717565b60405180910390a15b505050565b6111d761235b565b8060cd60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61122361235b565b8060d160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b61128661235b565b8060ce908161129591906148d4565b5050565b6112a161235b565b60008161ffff161180156112c857506116448161ffff1660ca546112c591906149a6565b11155b611307576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fe90614a48565b60405180910390fd5b6000600160ca5461131891906149a6565b905060005b8261ffff168161ffff1610156114065760008161ffff168361133f91906149a6565b90508460cf600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808573ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45080806113fe90614a68565b91505061131d565b508160d060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160048282829054906101000a900461ffff166114669190614a92565b92506101000a81548161ffff021916908361ffff1602179055508161ffff1660ca600082825461149691906149a6565b92505081905550505050565b60006114ad826114b4565b9050919050565b60006114bf82611f7f565b6114fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114f590614b16565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660cf600084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146115a65760cf600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506115dd565b60d2600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b919050565b60ff81565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611657576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164e90614ba8565b60405180910390fd5b60d060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160049054906101000a900461ffff1661ffff169050919050565b6116bb61235b565b6116c56000612682565b565b6702ea11e32ad5000081565b600a81565b60cb5481565b6116e661235b565b8060d460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6701f161421c8e000081565b61175561235b565b61175e47610d49565b565b600281565b600381565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60d46020528060005260406000206000915054906101000a900460ff1681565b6060609880546117c390614246565b80601f01602080910402602001604051908101604052809291908181526020018280546117ef90614246565b801561183c5780601f106118115761010080835404028352916020019161183c565b820191906000526020600020905b81548152906001019060200180831161181f57829003601f168201915b5050505050905090565b60cf6020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900461ffff16908060000160169054906101000a900460ff16908060000160179054906101000a900468ffffffffffffffffff16905084565b600181565b6118dd6118d6611f8e565b8383612748565b5050565b60006118eb611f8e565b9050600084826000866040516020016119079493929190614c79565b60405160208183030381529060405280519060200120905061192981846128b4565b73ffffffffffffffffffffffffffffffffffffffff1660cd60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146119b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119af90614d13565b60405180910390fd5b6119c1856123d9565b5050505050565b668e1bc9bf04000081565b6119e46119de611f8e565b836120f7565b611a23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a1a90614502565b60405180910390fd5b611a2f848484846128d0565b50505050565b6060611a4082611f7f565b611a7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a7690614da5565b60405180910390fd5b6000611a8961292c565b90506000815111611aa95760405180602001604052806000815250611ad4565b80611ab3846129be565b604051602001611ac4929190614e01565b6040516020818303038152906040525b915050919050565b60c75481565b60d36020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a90046bffffffffffffffffffffffff16905082565b6000611b48611f8e565b9050600081905060008282600187604051602001611b699493929190614c79565b604051602081830303815290604052805190602001209050611b8b81856128b4565b73ffffffffffffffffffffffffffffffffffffffff1660cd60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611c1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1190614d13565b60405180910390fd5b611c2382612b1e565b5050505050565b6000611c34611f8e565b9050600081868686604051602001611c4f9493929190614e25565b604051602081830303815290604052805190602001209050611c7181846128b4565b73ffffffffffffffffffffffffffffffffffffffff1660cd60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611d00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cf790614d13565b60405180910390fd5b611d0b828787612cde565b505050505050565b60008060cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1663c4552791866040518263ffffffff1660e01b8152600401611d8b9190613a66565b602060405180830381865afa158015611da8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dcc9190614eb1565b73ffffffffffffffffffffffffffffffffffffffff1603611df1576001915050611dff565b611dfb8484613064565b9150505b92915050565b611e0d61235b565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611e7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7390614f50565b60405180910390fd5b611e8581612682565b50565b6000611e92611f8e565b90508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611f02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ef990614fbc565b60405180910390fd5b611f0b82612b1e565b5050565b60c85481565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600060ca548211159050919050565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff160361203757600080368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509050600080369050905073ffffffffffffffffffffffffffffffffffffffff81830151169250505061203b565b3390505b90565b816099600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff166120b1836114a2565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061210282611f7f565b612141576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121389061504e565b60405180910390fd5b600061214c836114a2565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806121bb57508373ffffffffffffffffffffffffffffffffffffffff166121a384610afd565b73ffffffffffffffffffffffffffffffffffffffff16145b806121cc57506121cb8185611d13565b5b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff1660d360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614806122c2575060d46000612279611f8e565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b8061230c5750733b9edbc42ba4acedb4f2aa290aefbb40cd10fcac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b61234b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612342906150e0565b60405180910390fd5b612356838383612cde565b505050565b612363611f8e565b73ffffffffffffffffffffffffffffffffffffffff1661238161176a565b73ffffffffffffffffffffffffffffffffffffffff16146123d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123ce9061514c565b60405180910390fd5b565b60006123e3611f8e565b90508073ffffffffffffffffffffffffffffffffffffffff1660d360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146124b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124ac906151b8565b60405180910390fd5b600060d360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600015158173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f3b67ff8ac3416653f93a330afcba28980851459ed5e45b9f41bc46543adf163560405160405180910390a45050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600060019054906101000a900460ff1661260b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126029061524a565b60405180910390fd5b6126136130f8565b61261b613149565b612625828261319a565b5050565b600060019054906101000a900460ff16612678576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161266f9061524a565b60405180910390fd5b61268061320d565b565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036127b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127ad906152b6565b60405180910390fd5b80609a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516128a791906138c2565b60405180910390a3505050565b60006128c86128c28461326e565b8361329e565b905092915050565b6128db8484846121d5565b6128e7848484846132c5565b612926576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161291d90615348565b60405180910390fd5b50505050565b606060ce805461293b90614246565b80601f016020809104026020016040519081016040528092919081815260200182805461296790614246565b80156129b45780601f10612989576101008083540402835291602001916129b4565b820191906000526020600020905b81548152906001019060200180831161299757829003601f168201915b5050505050905090565b606060008203612a05576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612b19565b600082905060005b60008214612a37578080612a2090615368565b915050600a82612a3091906153df565b9150612a0d565b60008167ffffffffffffffff811115612a5357612a52613cf1565b5b6040519080825280601f01601f191660200182016040528015612a855781602001600182028036833780820191505090505b5090505b60008514612b1257600182612a9e919061445c565b9150600a85612aad9190615410565b6030612ab991906149a6565b60f81b818381518110612acf57612ace615441565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85612b0b91906153df565b9450612a89565b8093505050505b919050565b6000612b28611f8e565b9050600073ffffffffffffffffffffffffffffffffffffffff1660d360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bf2906154bc565b60405180910390fd5b8160d360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600115158273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f3b67ff8ac3416653f93a330afcba28980851459ed5e45b9f41bc46543adf163560405160405180910390a45050565b8273ffffffffffffffffffffffffffffffffffffffff16612cfe826114a2565b73ffffffffffffffffffffffffffffffffffffffff1614612d54576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d4b9061554e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612dc3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dba906155e0565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612e31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e289061564c565b60405180910390fd5b600060cf600083815260200190815260200160002060000160169054906101000a900460ff1660ff1614612e9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e91906156b8565b60405180910390fd5b612ea583838361344c565b612eb060008261203e565b600160d060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160048282829054906101000a900461ffff16612f1091906156d8565b92506101000a81548161ffff021916908361ffff160217905550600160d060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160048282829054906101000a900461ffff16612f8a9190614a92565b92506101000a81548161ffff021916908361ffff1602179055508160cf600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461305f838383613451565b505050565b6000609a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600060019054906101000a900460ff16613147576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161313e9061524a565b60405180910390fd5b565b600060019054906101000a900460ff16613198576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161318f9061524a565b60405180910390fd5b565b600060019054906101000a900460ff166131e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131e09061524a565b60405180910390fd5b81609790816131f891906148d4565b50806098908161320891906148d4565b505050565b600060019054906101000a900460ff1661325c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132539061524a565b60405180910390fd5b61326c613267611f8e565b612682565b565b6000816040516020016132819190615783565b604051602081830303815290604052805190602001209050919050565b60008060006132ad8585613456565b915091506132ba816134d7565b819250505092915050565b60006132e68473ffffffffffffffffffffffffffffffffffffffff16612599565b1561343f578373ffffffffffffffffffffffffffffffffffffffff1663150b7a0261330f611f8e565b8786866040518563ffffffff1660e01b815260040161333194939291906157fe565b6020604051808303816000875af192505050801561336d57506040513d601f19601f8201168201806040525081019061336a919061585f565b60015b6133ef573d806000811461339d576040519150601f19603f3d011682016040523d82523d6000602084013e6133a2565b606091505b5060008151036133e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133de90615348565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050613444565b600190505b949350505050565b505050565b505050565b60008060418351036134975760008060006020860151925060408601519150606086015160001a905061348b878285856136a3565b945094505050506134d0565b60408351036134c75760008060208501519150604085015190506134bc8683836137af565b9350935050506134d0565b60006002915091505b9250929050565b600060048111156134eb576134ea61588c565b5b8160048111156134fe576134fd61588c565b5b03156136a057600160048111156135185761351761588c565b5b81600481111561352b5761352a61588c565b5b0361356b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161356290615907565b60405180910390fd5b6002600481111561357f5761357e61588c565b5b8160048111156135925761359161588c565b5b036135d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135c990615973565b60405180910390fd5b600360048111156135e6576135e561588c565b5b8160048111156135f9576135f861588c565b5b03613639576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161363090615a05565b60405180910390fd5b60048081111561364c5761364b61588c565b5b81600481111561365f5761365e61588c565b5b0361369f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161369690615a97565b60405180910390fd5b5b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156136de5760006003915091506137a6565b601b8560ff16141580156136f65750601c8560ff1614155b156137085760006004915091506137a6565b60006001878787876040516000815260200160405260405161372d9493929190615ac6565b6020604051602081039080840390855afa15801561374f573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361379d576000600192509250506137a6565b80600092509250505b94509492505050565b60008060007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60001b841690506000601b60ff8660001c901c6137f291906149a6565b9050613800878288856136a3565b935093505050935093915050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61385781613822565b811461386257600080fd5b50565b6000813590506138748161384e565b92915050565b6000602082840312156138905761388f613818565b5b600061389e84828501613865565b91505092915050565b60008115159050919050565b6138bc816138a7565b82525050565b60006020820190506138d760008301846138b3565b92915050565b6000819050919050565b6138f0816138dd565b82525050565b600060208201905061390b60008301846138e7565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561394b578082015181840152602081019050613930565b8381111561395a576000848401525b50505050565b6000601f19601f8301169050919050565b600061397c82613911565b613986818561391c565b935061399681856020860161392d565b61399f81613960565b840191505092915050565b600060208201905081810360008301526139c48184613971565b905092915050565b6139d5816138dd565b81146139e057600080fd5b50565b6000813590506139f2816139cc565b92915050565b600060208284031215613a0e57613a0d613818565b5b6000613a1c848285016139e3565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613a5082613a25565b9050919050565b613a6081613a45565b82525050565b6000602082019050613a7b6000830184613a57565b92915050565b613a8a81613a45565b8114613a9557600080fd5b50565b600081359050613aa781613a81565b92915050565b60008060408385031215613ac457613ac3613818565b5b6000613ad285828601613a98565b9250506020613ae3858286016139e3565b9150509250929050565b600080600060608486031215613b0657613b05613818565b5b6000613b1486828701613a98565b9350506020613b2586828701613a98565b9250506040613b36868287016139e3565b9150509250925092565b600060208284031215613b5657613b55613818565b5b6000613b6484828501613a98565b91505092915050565b600060ff82169050919050565b613b8381613b6d565b82525050565b6000602082019050613b9e6000830184613b7a565b92915050565b600061ffff82169050919050565b613bbb81613ba4565b82525050565b600079ffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b613bf081613bc1565b82525050565b6000608082019050613c0b6000830187613bb2565b613c186020830186613bb2565b613c256040830185613bb2565b613c326060830184613be7565b95945050505050565b60008060408385031215613c5257613c51613818565b5b6000613c6085828601613a98565b9250506020613c7185828601613a98565b9150509250929050565b613c84816138a7565b8114613c8f57600080fd5b50565b600081359050613ca181613c7b565b92915050565b60008060408385031215613cbe57613cbd613818565b5b6000613ccc85828601613a98565b9250506020613cdd85828601613c92565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613d2982613960565b810181811067ffffffffffffffff82111715613d4857613d47613cf1565b5b80604052505050565b6000613d5b61380e565b9050613d678282613d20565b919050565b600067ffffffffffffffff821115613d8757613d86613cf1565b5b613d9082613960565b9050602081019050919050565b82818337600083830152505050565b6000613dbf613dba84613d6c565b613d51565b905082815260208101848484011115613ddb57613dda613cec565b5b613de6848285613d9d565b509392505050565b600082601f830112613e0357613e02613ce7565b5b8135613e13848260208601613dac565b91505092915050565b600060208284031215613e3257613e31613818565b5b600082013567ffffffffffffffff811115613e5057613e4f61381d565b5b613e5c84828501613dee565b91505092915050565b613e6e81613ba4565b8114613e7957600080fd5b50565b600081359050613e8b81613e65565b92915050565b60008060408385031215613ea857613ea7613818565b5b6000613eb685828601613a98565b9250506020613ec785828601613e7c565b9150509250929050565b6000602082019050613ee66000830184613bb2565b92915050565b600068ffffffffffffffffff82169050919050565b613f0a81613eec565b82525050565b6000608082019050613f256000830187613a57565b613f326020830186613bb2565b613f3f6040830185613b7a565b613f4c6060830184613f01565b95945050505050565b600067ffffffffffffffff821115613f7057613f6f613cf1565b5b613f7982613960565b9050602081019050919050565b6000613f99613f9484613f55565b613d51565b905082815260208101848484011115613fb557613fb4613cec565b5b613fc0848285613d9d565b509392505050565b600082601f830112613fdd57613fdc613ce7565b5b8135613fed848260208601613f86565b91505092915050565b60008060006060848603121561400f5761400e613818565b5b600061401d86828701613a98565b935050602061402e868287016139e3565b925050604084013567ffffffffffffffff81111561404f5761404e61381d565b5b61405b86828701613fc8565b9150509250925092565b6000806000806080858703121561407f5761407e613818565b5b600061408d87828801613a98565b945050602061409e87828801613a98565b93505060406140af878288016139e3565b925050606085013567ffffffffffffffff8111156140d0576140cf61381d565b5b6140dc87828801613fc8565b91505092959194509250565b60006bffffffffffffffffffffffff82169050919050565b614109816140e8565b82525050565b60006040820190506141246000830185613a57565b6141316020830184614100565b9392505050565b6000806040838503121561414f5761414e613818565b5b600061415d858286016139e3565b925050602083013567ffffffffffffffff81111561417e5761417d61381d565b5b61418a85828601613fc8565b9150509250929050565b600080600080608085870312156141ae576141ad613818565b5b60006141bc87828801613a98565b94505060206141cd878288016139e3565b93505060406141de878288016139e3565b925050606085013567ffffffffffffffff8111156141ff576141fe61381d565b5b61420b87828801613fc8565b91505092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061425e57607f821691505b60208210810361427157614270614217565b5b50919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b60006142d3602c8361391c565b91506142de82614277565b604082019050919050565b60006020820190508181036000830152614302816142c6565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b600061436560218361391c565b915061437082614309565b604082019050919050565b6000602082019050818103600083015261439481614358565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b60006143f760388361391c565b91506144028261439b565b604082019050919050565b60006020820190508181036000830152614426816143ea565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614467826138dd565b9150614472836138dd565b9250828210156144855761448461442d565b5b828203905092915050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b60006144ec60318361391c565b91506144f782614490565b604082019050919050565b6000602082019050818103600083015261451b816144df565b9050919050565b600081905092915050565b50565b600061453d600083614522565b91506145488261452d565b600082019050919050565b600061455e82614530565b9150819050919050565b7f5769746864726177206661696c65640000000000000000000000000000000000600082015250565b600061459e600f8361391c565b91506145a982614568565b602082019050919050565b600060208201905081810360008301526145cd81614591565b9050919050565b7f424150433a2063616e7420756e6c6f636b207468656d73656c76657300000000600082015250565b600061460a601c8361391c565b9150614615826145d4565b602082019050919050565b60006020820190508181036000830152614639816145fd565b9050919050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b600061469c602e8361391c565b91506146a782614640565b604082019050919050565b600060208201905081810360008301526146cb8161468f565b9050919050565b6000819050919050565b6000819050919050565b60006147016146fc6146f7846146d2565b6146dc565b613b6d565b9050919050565b614711816146e6565b82525050565b600060208201905061472c6000830184614708565b92915050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026147947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614757565b61479e8683614757565b95508019841693508086168417925050509392505050565b60006147d16147cc6147c7846138dd565b6146dc565b6138dd565b9050919050565b6000819050919050565b6147eb836147b6565b6147ff6147f7826147d8565b848454614764565b825550505050565b600090565b614814614807565b61481f8184846147e2565b505050565b5b818110156148435761483860008261480c565b600181019050614825565b5050565b601f8211156148885761485981614732565b61486284614747565b81016020851015614871578190505b61488561487d85614747565b830182614824565b50505b505050565b600082821c905092915050565b60006148ab6000198460080261488d565b1980831691505092915050565b60006148c4838361489a565b9150826002028217905092915050565b6148dd82613911565b67ffffffffffffffff8111156148f6576148f5613cf1565b5b6149008254614246565b61490b828285614847565b600060209050601f83116001811461493e576000841561492c578287015190505b61493685826148b8565b86555061499e565b601f19841661494c86614732565b60005b828110156149745784890151825560018201915060208501945060208101905061494f565b86831015614991578489015161498d601f89168261489a565b8355505b6001600288020188555050505b505050505050565b60006149b1826138dd565b91506149bc836138dd565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156149f1576149f061442d565b5b828201905092915050565b7f424150433a20696e76616c696420616d6f756e74000000000000000000000000600082015250565b6000614a3260148361391c565b9150614a3d826149fc565b602082019050919050565b60006020820190508181036000830152614a6181614a25565b9050919050565b6000614a7382613ba4565b915061ffff8203614a8757614a8661442d565b5b600182019050919050565b6000614a9d82613ba4565b9150614aa883613ba4565b92508261ffff03821115614abf57614abe61442d565b5b828201905092915050565b7f4552433732313a20746f6b656e20646f6573206e6f7420657869737400000000600082015250565b6000614b00601c8361391c565b9150614b0b82614aca565b602082019050919050565b60006020820190508181036000830152614b2f81614af3565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b6000614b92602a8361391c565b9150614b9d82614b36565b604082019050919050565b60006020820190508181036000830152614bc181614b85565b9050919050565b60008160601b9050919050565b6000614be082614bc8565b9050919050565b6000614bf282614bd5565b9050919050565b614c0a614c0582613a45565b614be7565b82525050565b60008160f81b9050919050565b6000614c2882614c10565b9050919050565b6000614c3a82614c1d565b9050919050565b614c52614c4d826138a7565b614c2f565b82525050565b6000819050919050565b614c73614c6e826138dd565b614c58565b82525050565b6000614c858287614bf9565b601482019150614c958286614bf9565b601482019150614ca58285614c41565b600182019150614cb58284614c62565b60208201915081905095945050505050565b7f424150433a20696e76616c6964207369676e6174757265000000000000000000600082015250565b6000614cfd60178361391c565b9150614d0882614cc7565b602082019050919050565b60006020820190508181036000830152614d2c81614cf0565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000614d8f602f8361391c565b9150614d9a82614d33565b604082019050919050565b60006020820190508181036000830152614dbe81614d82565b9050919050565b600081905092915050565b6000614ddb82613911565b614de58185614dc5565b9350614df581856020860161392d565b80840191505092915050565b6000614e0d8285614dd0565b9150614e198284614dd0565b91508190509392505050565b6000614e318287614bf9565b601482019150614e418286614bf9565b601482019150614e518285614c62565b602082019150614e618284614c62565b60208201915081905095945050505050565b6000614e7e82613a45565b9050919050565b614e8e81614e73565b8114614e9957600080fd5b50565b600081519050614eab81614e85565b92915050565b600060208284031215614ec757614ec6613818565b5b6000614ed584828501614e9c565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614f3a60268361391c565b9150614f4582614ede565b604082019050919050565b60006020820190508181036000830152614f6981614f2d565b9050919050565b7f424150433a2063616e74206c6f636b207468656d73656c766573000000000000600082015250565b6000614fa6601a8361391c565b9150614fb182614f70565b602082019050919050565b60006020820190508181036000830152614fd581614f99565b9050919050565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000615038602c8361391c565b915061504382614fdc565b604082019050919050565b600060208201905081810360008301526150678161502b565b9050919050565b7f424150433a206f776e6572206973206c6f636b656420666f72207472616e736660008201527f6572730000000000000000000000000000000000000000000000000000000000602082015250565b60006150ca60238361391c565b91506150d58261506e565b604082019050919050565b600060208201905081810360008301526150f9816150bd565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061513660208361391c565b915061514182615100565b602082019050919050565b6000602082019050818103600083015261516581615129565b9050919050565b7f424150433a2063616e7420756e6c6f636b20746869732077616c6c6574000000600082015250565b60006151a2601d8361391c565b91506151ad8261516c565b602082019050919050565b600060208201905081810360008301526151d181615195565b9050919050565b7f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960008201527f6e697469616c697a696e67000000000000000000000000000000000000000000602082015250565b6000615234602b8361391c565b915061523f826151d8565b604082019050919050565b6000602082019050818103600083015261526381615227565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b60006152a060198361391c565b91506152ab8261526a565b602082019050919050565b600060208201905081810360008301526152cf81615293565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b600061533260328361391c565b915061533d826152d6565b604082019050919050565b6000602082019050818103600083015261536181615325565b9050919050565b6000615373826138dd565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036153a5576153a461442d565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006153ea826138dd565b91506153f5836138dd565b925082615405576154046153b0565b5b828204905092915050565b600061541b826138dd565b9150615426836138dd565b925082615436576154356153b0565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f424150433a20616c7265616479206c6f636b6564000000000000000000000000600082015250565b60006154a660148361391c565b91506154b182615470565b602082019050919050565b600060208201905081810360008301526154d581615499565b9050919050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b600061553860258361391c565b9150615543826154dc565b604082019050919050565b600060208201905081810360008301526155678161552b565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b60006155ca60248361391c565b91506155d58261556e565b604082019050919050565b600060208201905081810360008301526155f9816155bd565b9050919050565b7f4552433732313a2063616e2774207472616e73666572207468656d73656c6600600082015250565b6000615636601f8361391c565b915061564182615600565b602082019050919050565b6000602082019050818103600083015261566581615629565b9050919050565b7f424150433a20746f6b656e2063616e2774206265207472616e73666572726564600082015250565b60006156a260208361391c565b91506156ad8261566c565b602082019050919050565b600060208201905081810360008301526156d181615695565b9050919050565b60006156e382613ba4565b91506156ee83613ba4565b9250828210156157015761570061442d565b5b828203905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b6000615742601c83614dc5565b915061574d8261570c565b601c82019050919050565b6000819050919050565b6000819050919050565b61577d61577882615758565b615762565b82525050565b600061578e82615735565b915061579a828461576c565b60208201915081905092915050565b600081519050919050565b600082825260208201905092915050565b60006157d0826157a9565b6157da81856157b4565b93506157ea81856020860161392d565b6157f381613960565b840191505092915050565b60006080820190506158136000830187613a57565b6158206020830186613a57565b61582d60408301856138e7565b818103606083015261583f81846157c5565b905095945050505050565b6000815190506158598161384e565b92915050565b60006020828403121561587557615874613818565b5b60006158838482850161584a565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b60006158f160188361391c565b91506158fc826158bb565b602082019050919050565b60006020820190508181036000830152615920816158e4565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b600061595d601f8361391c565b915061596882615927565b602082019050919050565b6000602082019050818103600083015261598c81615950565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b60006159ef60228361391c565b91506159fa82615993565b604082019050919050565b60006020820190508181036000830152615a1e816159e2565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000615a8160228361391c565b9150615a8c82615a25565b604082019050919050565b60006020820190508181036000830152615ab081615a74565b9050919050565b615ac081615758565b82525050565b6000608082019050615adb6000830187615ab7565b615ae86020830186613b7a565b615af56040830185615ab7565b615b026060830184615ab7565b9594505050505056fea264697066735822122017bf961e91daab9297a4ad60d01ea315a0d8ea88b995bcc6503f775e58f5673c64736f6c634300080f0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102f15760003560e01c80637245bd5b1161019d578063a22cb465116100e9578063cbf9fe5f116100a2578063e985e9c51161007c578063e985e9c5146108fd578063f2fde38b1461092d578063f435f5a714610949578063f9c7324114610965576102f1565b8063cbf9fe5f14610894578063d8f7c836146108c5578063dabd76e9146108e1576102f1565b8063a22cb465146107d4578063abee0803146107f0578063af8d6ad81461080c578063b88d4fde1461082a578063c87b56dd14610846578063ca6cffd114610876576102f1565b806386ccdecf116101565780638e8f294b116101305780638e8f294b1461073557806395d89b41146107655780639745cc3d146107835780639e2c0b23146107b6576102f1565b806386ccdecf146106db5780638c418eb2146106f95780638da5cb5b14610717576102f1565b80637245bd5b1461063d578063725ce2891461065b57806373f42561146106795780637419e77a14610697578063747a7761146106b3578063853828b6146106d1576102f1565b8063407b5ee61161025c57806355f804b3116102155780636db021ee116101ef5780636db021ee146105b55780636f8e76f5146105e557806370a0823114610603578063715018a614610633576102f1565b806355f804b31461054d578063597dfb98146105695780636352211e14610585576102f1565b8063407b5ee61461048c578063408b3cdb146104aa57806342842e0e146104dd578063485cc955146104f95780635437988d14610515578063558a729714610531576102f1565b8063197a089c116102ae578063197a089c146103cc57806323b872dd146103ea5780632a29ad14146104065780632e1a7d4d146104365780632f6c493c1461045257806332cb6b0c1461046e576102f1565b806301ffc9a7146102f6578063047fc9aa1461032657806306fdde0314610344578063081812fc14610362578063095ea7b31461039257806318160ddd146103ae575b600080fd5b610310600480360381019061030b919061387a565b610983565b60405161031d91906138c2565b60405180910390f35b61032e610a65565b60405161033b91906138f6565b60405180910390f35b61034c610a6b565b60405161035991906139aa565b60405180910390f35b61037c600480360381019061037791906139f8565b610afd565b6040516103899190613a66565b60405180910390f35b6103ac60048036038101906103a79190613aad565b610b82565b005b6103b6610c99565b6040516103c391906138f6565b60405180910390f35b6103d4610cb0565b6040516103e191906138f6565b60405180910390f35b61040460048036038101906103ff9190613aed565b610cb6565b005b610420600480360381019061041b91906139f8565b610d16565b60405161042d9190613a66565b60405180910390f35b610450600480360381019061044b91906139f8565b610d49565b005b61046c60048036038101906104679190613b40565b610e08565b005b610476610e8f565b60405161048391906138f6565b60405180910390f35b610494610e95565b6040516104a19190613b89565b60405180910390f35b6104c460048036038101906104bf9190613b40565b610e9a565b6040516104d49493929190613bf6565b60405180910390f35b6104f760048036038101906104f29190613aed565b610f1a565b005b610513600480360381019061050e9190613c3b565b610f3a565b005b61052f600480360381019061052a9190613b40565b6111cf565b005b61054b60048036038101906105469190613ca7565b61121b565b005b61056760048036038101906105629190613e1c565b61127e565b005b610583600480360381019061057e9190613e91565b611299565b005b61059f600480360381019061059a91906139f8565b6114a2565b6040516105ac9190613a66565b60405180910390f35b6105cf60048036038101906105ca91906139f8565b6114b4565b6040516105dc9190613a66565b60405180910390f35b6105ed6115e2565b6040516105fa9190613b89565b60405180910390f35b61061d60048036038101906106189190613b40565b6115e7565b60405161062a91906138f6565b60405180910390f35b61063b6116b3565b005b6106456116c7565b60405161065291906138f6565b60405180910390f35b6106636116d3565b6040516106709190613ed1565b60405180910390f35b6106816116d8565b60405161068e91906138f6565b60405180910390f35b6106b160048036038101906106ac9190613ca7565b6116de565b005b6106bb611741565b6040516106c891906138f6565b60405180910390f35b6106d961174d565b005b6106e3611760565b6040516106f09190613ed1565b60405180910390f35b610701611765565b60405161070e9190613ed1565b60405180910390f35b61071f61176a565b60405161072c9190613a66565b60405180910390f35b61074f600480360381019061074a9190613b40565b611794565b60405161075c91906138c2565b60405180910390f35b61076d6117b4565b60405161077a91906139aa565b60405180910390f35b61079d600480360381019061079891906139f8565b611846565b6040516107ad9493929190613f10565b60405180910390f35b6107be6118c6565b6040516107cb9190613ed1565b60405180910390f35b6107ee60048036038101906107e99190613ca7565b6118cb565b005b61080a60048036038101906108059190613ff6565b6118e1565b005b6108146119c8565b60405161082191906138f6565b60405180910390f35b610844600480360381019061083f9190614065565b6119d3565b005b610860600480360381019061085b91906139f8565b611a35565b60405161086d91906139aa565b60405180910390f35b61087e611adc565b60405161088b91906138f6565b60405180910390f35b6108ae60048036038101906108a99190613b40565b611ae2565b6040516108bc92919061410f565b60405180910390f35b6108df60048036038101906108da9190614138565b611b3e565b005b6108fb60048036038101906108f69190614194565b611c2a565b005b61091760048036038101906109129190613c3b565b611d13565b60405161092491906138c2565b60405180910390f35b61094760048036038101906109429190613b40565b611e05565b005b610963600480360381019061095e9190613b40565b611e88565b005b61096d611f0f565b60405161097a91906138f6565b60405180910390f35b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610a4e57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610a5e5750610a5d82611f15565b5b9050919050565b60ca5481565b606060978054610a7a90614246565b80601f0160208091040260200160405190810160405280929190818152602001828054610aa690614246565b8015610af35780601f10610ac857610100808354040283529160200191610af3565b820191906000526020600020905b815481529060010190602001808311610ad657829003601f168201915b5050505050905090565b6000610b0882611f7f565b610b47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3e906142e9565b60405180910390fd5b6099600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610b8d826114a2565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610bfd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf49061437b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610c1c611f8e565b73ffffffffffffffffffffffffffffffffffffffff161480610c4b5750610c4a81610c45611f8e565b611d13565b5b610c8a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c819061440d565b60405180910390fd5b610c94838361203e565b505050565b600060cb5460ca54610cab919061445c565b905090565b60c95481565b610cc7610cc1611f8e565b826120f7565b610d06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cfd90614502565b60405180910390fd5b610d118383836121d5565b505050565b60d26020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610d5161235b565b6000610d5b611f8e565b73ffffffffffffffffffffffffffffffffffffffff1682604051610d7e90614553565b60006040518083038185875af1925050503d8060008114610dbb576040519150601f19603f3d011682016040523d82523d6000602084013e610dc0565b606091505b5050905080610e04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfb906145b4565b60405180910390fd5b5050565b6000610e12611f8e565b90508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610e82576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7990614620565b60405180910390fd5b610e8b826123d9565b5050565b61164481565b60fe81565b60d06020528060005260406000206000915090508060000160009054906101000a900461ffff16908060000160029054906101000a900461ffff16908060000160049054906101000a900461ffff16908060000160069054906101000a900479ffffffffffffffffffffffffffffffffffffffffffffffffffff16905084565b610f35838383604051806020016040528060008152506119d3565b505050565b60008060019054906101000a900460ff16159050808015610f6b5750600160008054906101000a900460ff1660ff16105b80610f985750610f7a30612599565b158015610f975750600160008054906101000a900460ff1660ff16145b5b610fd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fce906146b2565b60405180910390fd5b60016000806101000a81548160ff021916908360ff1602179055508015611014576001600060016101000a81548160ff0219169083151502179055505b6110886040518060400160405280600a81526020017f50697261746541706573000000000000000000000000000000000000000000008152506040518060400160405280600481526020017f42415043000000000000000000000000000000000000000000000000000000008152506125bc565b611090612629565b8260cd60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160cc60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160d16000611120611f8e565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555080156111ca5760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860016040516111c19190614717565b60405180910390a15b505050565b6111d761235b565b8060cd60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61122361235b565b8060d160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b61128661235b565b8060ce908161129591906148d4565b5050565b6112a161235b565b60008161ffff161180156112c857506116448161ffff1660ca546112c591906149a6565b11155b611307576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fe90614a48565b60405180910390fd5b6000600160ca5461131891906149a6565b905060005b8261ffff168161ffff1610156114065760008161ffff168361133f91906149a6565b90508460cf600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808573ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45080806113fe90614a68565b91505061131d565b508160d060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160048282829054906101000a900461ffff166114669190614a92565b92506101000a81548161ffff021916908361ffff1602179055508161ffff1660ca600082825461149691906149a6565b92505081905550505050565b60006114ad826114b4565b9050919050565b60006114bf82611f7f565b6114fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114f590614b16565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660cf600084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146115a65760cf600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506115dd565b60d2600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b919050565b60ff81565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611657576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164e90614ba8565b60405180910390fd5b60d060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160049054906101000a900461ffff1661ffff169050919050565b6116bb61235b565b6116c56000612682565b565b6702ea11e32ad5000081565b600a81565b60cb5481565b6116e661235b565b8060d460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6701f161421c8e000081565b61175561235b565b61175e47610d49565b565b600281565b600381565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60d46020528060005260406000206000915054906101000a900460ff1681565b6060609880546117c390614246565b80601f01602080910402602001604051908101604052809291908181526020018280546117ef90614246565b801561183c5780601f106118115761010080835404028352916020019161183c565b820191906000526020600020905b81548152906001019060200180831161181f57829003601f168201915b5050505050905090565b60cf6020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900461ffff16908060000160169054906101000a900460ff16908060000160179054906101000a900468ffffffffffffffffff16905084565b600181565b6118dd6118d6611f8e565b8383612748565b5050565b60006118eb611f8e565b9050600084826000866040516020016119079493929190614c79565b60405160208183030381529060405280519060200120905061192981846128b4565b73ffffffffffffffffffffffffffffffffffffffff1660cd60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146119b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119af90614d13565b60405180910390fd5b6119c1856123d9565b5050505050565b668e1bc9bf04000081565b6119e46119de611f8e565b836120f7565b611a23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a1a90614502565b60405180910390fd5b611a2f848484846128d0565b50505050565b6060611a4082611f7f565b611a7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a7690614da5565b60405180910390fd5b6000611a8961292c565b90506000815111611aa95760405180602001604052806000815250611ad4565b80611ab3846129be565b604051602001611ac4929190614e01565b6040516020818303038152906040525b915050919050565b60c75481565b60d36020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a90046bffffffffffffffffffffffff16905082565b6000611b48611f8e565b9050600081905060008282600187604051602001611b699493929190614c79565b604051602081830303815290604052805190602001209050611b8b81856128b4565b73ffffffffffffffffffffffffffffffffffffffff1660cd60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611c1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1190614d13565b60405180910390fd5b611c2382612b1e565b5050505050565b6000611c34611f8e565b9050600081868686604051602001611c4f9493929190614e25565b604051602081830303815290604052805190602001209050611c7181846128b4565b73ffffffffffffffffffffffffffffffffffffffff1660cd60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611d00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cf790614d13565b60405180910390fd5b611d0b828787612cde565b505050505050565b60008060cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1663c4552791866040518263ffffffff1660e01b8152600401611d8b9190613a66565b602060405180830381865afa158015611da8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dcc9190614eb1565b73ffffffffffffffffffffffffffffffffffffffff1603611df1576001915050611dff565b611dfb8484613064565b9150505b92915050565b611e0d61235b565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611e7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7390614f50565b60405180910390fd5b611e8581612682565b50565b6000611e92611f8e565b90508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611f02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ef990614fbc565b60405180910390fd5b611f0b82612b1e565b5050565b60c85481565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600060ca548211159050919050565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff160361203757600080368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509050600080369050905073ffffffffffffffffffffffffffffffffffffffff81830151169250505061203b565b3390505b90565b816099600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff166120b1836114a2565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061210282611f7f565b612141576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121389061504e565b60405180910390fd5b600061214c836114a2565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806121bb57508373ffffffffffffffffffffffffffffffffffffffff166121a384610afd565b73ffffffffffffffffffffffffffffffffffffffff16145b806121cc57506121cb8185611d13565b5b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff1660d360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614806122c2575060d46000612279611f8e565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b8061230c5750733b9edbc42ba4acedb4f2aa290aefbb40cd10fcac73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b61234b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612342906150e0565b60405180910390fd5b612356838383612cde565b505050565b612363611f8e565b73ffffffffffffffffffffffffffffffffffffffff1661238161176a565b73ffffffffffffffffffffffffffffffffffffffff16146123d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123ce9061514c565b60405180910390fd5b565b60006123e3611f8e565b90508073ffffffffffffffffffffffffffffffffffffffff1660d360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146124b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124ac906151b8565b60405180910390fd5b600060d360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600015158173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f3b67ff8ac3416653f93a330afcba28980851459ed5e45b9f41bc46543adf163560405160405180910390a45050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600060019054906101000a900460ff1661260b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126029061524a565b60405180910390fd5b6126136130f8565b61261b613149565b612625828261319a565b5050565b600060019054906101000a900460ff16612678576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161266f9061524a565b60405180910390fd5b61268061320d565b565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036127b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127ad906152b6565b60405180910390fd5b80609a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516128a791906138c2565b60405180910390a3505050565b60006128c86128c28461326e565b8361329e565b905092915050565b6128db8484846121d5565b6128e7848484846132c5565b612926576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161291d90615348565b60405180910390fd5b50505050565b606060ce805461293b90614246565b80601f016020809104026020016040519081016040528092919081815260200182805461296790614246565b80156129b45780601f10612989576101008083540402835291602001916129b4565b820191906000526020600020905b81548152906001019060200180831161299757829003601f168201915b5050505050905090565b606060008203612a05576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612b19565b600082905060005b60008214612a37578080612a2090615368565b915050600a82612a3091906153df565b9150612a0d565b60008167ffffffffffffffff811115612a5357612a52613cf1565b5b6040519080825280601f01601f191660200182016040528015612a855781602001600182028036833780820191505090505b5090505b60008514612b1257600182612a9e919061445c565b9150600a85612aad9190615410565b6030612ab991906149a6565b60f81b818381518110612acf57612ace615441565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85612b0b91906153df565b9450612a89565b8093505050505b919050565b6000612b28611f8e565b9050600073ffffffffffffffffffffffffffffffffffffffff1660d360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bf2906154bc565b60405180910390fd5b8160d360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600115158273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f3b67ff8ac3416653f93a330afcba28980851459ed5e45b9f41bc46543adf163560405160405180910390a45050565b8273ffffffffffffffffffffffffffffffffffffffff16612cfe826114a2565b73ffffffffffffffffffffffffffffffffffffffff1614612d54576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d4b9061554e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612dc3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dba906155e0565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612e31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e289061564c565b60405180910390fd5b600060cf600083815260200190815260200160002060000160169054906101000a900460ff1660ff1614612e9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e91906156b8565b60405180910390fd5b612ea583838361344c565b612eb060008261203e565b600160d060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160048282829054906101000a900461ffff16612f1091906156d8565b92506101000a81548161ffff021916908361ffff160217905550600160d060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160048282829054906101000a900461ffff16612f8a9190614a92565b92506101000a81548161ffff021916908361ffff1602179055508160cf600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461305f838383613451565b505050565b6000609a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600060019054906101000a900460ff16613147576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161313e9061524a565b60405180910390fd5b565b600060019054906101000a900460ff16613198576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161318f9061524a565b60405180910390fd5b565b600060019054906101000a900460ff166131e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131e09061524a565b60405180910390fd5b81609790816131f891906148d4565b50806098908161320891906148d4565b505050565b600060019054906101000a900460ff1661325c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132539061524a565b60405180910390fd5b61326c613267611f8e565b612682565b565b6000816040516020016132819190615783565b604051602081830303815290604052805190602001209050919050565b60008060006132ad8585613456565b915091506132ba816134d7565b819250505092915050565b60006132e68473ffffffffffffffffffffffffffffffffffffffff16612599565b1561343f578373ffffffffffffffffffffffffffffffffffffffff1663150b7a0261330f611f8e565b8786866040518563ffffffff1660e01b815260040161333194939291906157fe565b6020604051808303816000875af192505050801561336d57506040513d601f19601f8201168201806040525081019061336a919061585f565b60015b6133ef573d806000811461339d576040519150601f19603f3d011682016040523d82523d6000602084013e6133a2565b606091505b5060008151036133e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133de90615348565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050613444565b600190505b949350505050565b505050565b505050565b60008060418351036134975760008060006020860151925060408601519150606086015160001a905061348b878285856136a3565b945094505050506134d0565b60408351036134c75760008060208501519150604085015190506134bc8683836137af565b9350935050506134d0565b60006002915091505b9250929050565b600060048111156134eb576134ea61588c565b5b8160048111156134fe576134fd61588c565b5b03156136a057600160048111156135185761351761588c565b5b81600481111561352b5761352a61588c565b5b0361356b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161356290615907565b60405180910390fd5b6002600481111561357f5761357e61588c565b5b8160048111156135925761359161588c565b5b036135d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135c990615973565b60405180910390fd5b600360048111156135e6576135e561588c565b5b8160048111156135f9576135f861588c565b5b03613639576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161363090615a05565b60405180910390fd5b60048081111561364c5761364b61588c565b5b81600481111561365f5761365e61588c565b5b0361369f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161369690615a97565b60405180910390fd5b5b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156136de5760006003915091506137a6565b601b8560ff16141580156136f65750601c8560ff1614155b156137085760006004915091506137a6565b60006001878787876040516000815260200160405260405161372d9493929190615ac6565b6020604051602081039080840390855afa15801561374f573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361379d576000600192509250506137a6565b80600092509250505b94509492505050565b60008060007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60001b841690506000601b60ff8660001c901c6137f291906149a6565b9050613800878288856136a3565b935093505050935093915050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61385781613822565b811461386257600080fd5b50565b6000813590506138748161384e565b92915050565b6000602082840312156138905761388f613818565b5b600061389e84828501613865565b91505092915050565b60008115159050919050565b6138bc816138a7565b82525050565b60006020820190506138d760008301846138b3565b92915050565b6000819050919050565b6138f0816138dd565b82525050565b600060208201905061390b60008301846138e7565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561394b578082015181840152602081019050613930565b8381111561395a576000848401525b50505050565b6000601f19601f8301169050919050565b600061397c82613911565b613986818561391c565b935061399681856020860161392d565b61399f81613960565b840191505092915050565b600060208201905081810360008301526139c48184613971565b905092915050565b6139d5816138dd565b81146139e057600080fd5b50565b6000813590506139f2816139cc565b92915050565b600060208284031215613a0e57613a0d613818565b5b6000613a1c848285016139e3565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613a5082613a25565b9050919050565b613a6081613a45565b82525050565b6000602082019050613a7b6000830184613a57565b92915050565b613a8a81613a45565b8114613a9557600080fd5b50565b600081359050613aa781613a81565b92915050565b60008060408385031215613ac457613ac3613818565b5b6000613ad285828601613a98565b9250506020613ae3858286016139e3565b9150509250929050565b600080600060608486031215613b0657613b05613818565b5b6000613b1486828701613a98565b9350506020613b2586828701613a98565b9250506040613b36868287016139e3565b9150509250925092565b600060208284031215613b5657613b55613818565b5b6000613b6484828501613a98565b91505092915050565b600060ff82169050919050565b613b8381613b6d565b82525050565b6000602082019050613b9e6000830184613b7a565b92915050565b600061ffff82169050919050565b613bbb81613ba4565b82525050565b600079ffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b613bf081613bc1565b82525050565b6000608082019050613c0b6000830187613bb2565b613c186020830186613bb2565b613c256040830185613bb2565b613c326060830184613be7565b95945050505050565b60008060408385031215613c5257613c51613818565b5b6000613c6085828601613a98565b9250506020613c7185828601613a98565b9150509250929050565b613c84816138a7565b8114613c8f57600080fd5b50565b600081359050613ca181613c7b565b92915050565b60008060408385031215613cbe57613cbd613818565b5b6000613ccc85828601613a98565b9250506020613cdd85828601613c92565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613d2982613960565b810181811067ffffffffffffffff82111715613d4857613d47613cf1565b5b80604052505050565b6000613d5b61380e565b9050613d678282613d20565b919050565b600067ffffffffffffffff821115613d8757613d86613cf1565b5b613d9082613960565b9050602081019050919050565b82818337600083830152505050565b6000613dbf613dba84613d6c565b613d51565b905082815260208101848484011115613ddb57613dda613cec565b5b613de6848285613d9d565b509392505050565b600082601f830112613e0357613e02613ce7565b5b8135613e13848260208601613dac565b91505092915050565b600060208284031215613e3257613e31613818565b5b600082013567ffffffffffffffff811115613e5057613e4f61381d565b5b613e5c84828501613dee565b91505092915050565b613e6e81613ba4565b8114613e7957600080fd5b50565b600081359050613e8b81613e65565b92915050565b60008060408385031215613ea857613ea7613818565b5b6000613eb685828601613a98565b9250506020613ec785828601613e7c565b9150509250929050565b6000602082019050613ee66000830184613bb2565b92915050565b600068ffffffffffffffffff82169050919050565b613f0a81613eec565b82525050565b6000608082019050613f256000830187613a57565b613f326020830186613bb2565b613f3f6040830185613b7a565b613f4c6060830184613f01565b95945050505050565b600067ffffffffffffffff821115613f7057613f6f613cf1565b5b613f7982613960565b9050602081019050919050565b6000613f99613f9484613f55565b613d51565b905082815260208101848484011115613fb557613fb4613cec565b5b613fc0848285613d9d565b509392505050565b600082601f830112613fdd57613fdc613ce7565b5b8135613fed848260208601613f86565b91505092915050565b60008060006060848603121561400f5761400e613818565b5b600061401d86828701613a98565b935050602061402e868287016139e3565b925050604084013567ffffffffffffffff81111561404f5761404e61381d565b5b61405b86828701613fc8565b9150509250925092565b6000806000806080858703121561407f5761407e613818565b5b600061408d87828801613a98565b945050602061409e87828801613a98565b93505060406140af878288016139e3565b925050606085013567ffffffffffffffff8111156140d0576140cf61381d565b5b6140dc87828801613fc8565b91505092959194509250565b60006bffffffffffffffffffffffff82169050919050565b614109816140e8565b82525050565b60006040820190506141246000830185613a57565b6141316020830184614100565b9392505050565b6000806040838503121561414f5761414e613818565b5b600061415d858286016139e3565b925050602083013567ffffffffffffffff81111561417e5761417d61381d565b5b61418a85828601613fc8565b9150509250929050565b600080600080608085870312156141ae576141ad613818565b5b60006141bc87828801613a98565b94505060206141cd878288016139e3565b93505060406141de878288016139e3565b925050606085013567ffffffffffffffff8111156141ff576141fe61381d565b5b61420b87828801613fc8565b91505092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061425e57607f821691505b60208210810361427157614270614217565b5b50919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b60006142d3602c8361391c565b91506142de82614277565b604082019050919050565b60006020820190508181036000830152614302816142c6565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b600061436560218361391c565b915061437082614309565b604082019050919050565b6000602082019050818103600083015261439481614358565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b60006143f760388361391c565b91506144028261439b565b604082019050919050565b60006020820190508181036000830152614426816143ea565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614467826138dd565b9150614472836138dd565b9250828210156144855761448461442d565b5b828203905092915050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b60006144ec60318361391c565b91506144f782614490565b604082019050919050565b6000602082019050818103600083015261451b816144df565b9050919050565b600081905092915050565b50565b600061453d600083614522565b91506145488261452d565b600082019050919050565b600061455e82614530565b9150819050919050565b7f5769746864726177206661696c65640000000000000000000000000000000000600082015250565b600061459e600f8361391c565b91506145a982614568565b602082019050919050565b600060208201905081810360008301526145cd81614591565b9050919050565b7f424150433a2063616e7420756e6c6f636b207468656d73656c76657300000000600082015250565b600061460a601c8361391c565b9150614615826145d4565b602082019050919050565b60006020820190508181036000830152614639816145fd565b9050919050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b600061469c602e8361391c565b91506146a782614640565b604082019050919050565b600060208201905081810360008301526146cb8161468f565b9050919050565b6000819050919050565b6000819050919050565b60006147016146fc6146f7846146d2565b6146dc565b613b6d565b9050919050565b614711816146e6565b82525050565b600060208201905061472c6000830184614708565b92915050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026147947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614757565b61479e8683614757565b95508019841693508086168417925050509392505050565b60006147d16147cc6147c7846138dd565b6146dc565b6138dd565b9050919050565b6000819050919050565b6147eb836147b6565b6147ff6147f7826147d8565b848454614764565b825550505050565b600090565b614814614807565b61481f8184846147e2565b505050565b5b818110156148435761483860008261480c565b600181019050614825565b5050565b601f8211156148885761485981614732565b61486284614747565b81016020851015614871578190505b61488561487d85614747565b830182614824565b50505b505050565b600082821c905092915050565b60006148ab6000198460080261488d565b1980831691505092915050565b60006148c4838361489a565b9150826002028217905092915050565b6148dd82613911565b67ffffffffffffffff8111156148f6576148f5613cf1565b5b6149008254614246565b61490b828285614847565b600060209050601f83116001811461493e576000841561492c578287015190505b61493685826148b8565b86555061499e565b601f19841661494c86614732565b60005b828110156149745784890151825560018201915060208501945060208101905061494f565b86831015614991578489015161498d601f89168261489a565b8355505b6001600288020188555050505b505050505050565b60006149b1826138dd565b91506149bc836138dd565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156149f1576149f061442d565b5b828201905092915050565b7f424150433a20696e76616c696420616d6f756e74000000000000000000000000600082015250565b6000614a3260148361391c565b9150614a3d826149fc565b602082019050919050565b60006020820190508181036000830152614a6181614a25565b9050919050565b6000614a7382613ba4565b915061ffff8203614a8757614a8661442d565b5b600182019050919050565b6000614a9d82613ba4565b9150614aa883613ba4565b92508261ffff03821115614abf57614abe61442d565b5b828201905092915050565b7f4552433732313a20746f6b656e20646f6573206e6f7420657869737400000000600082015250565b6000614b00601c8361391c565b9150614b0b82614aca565b602082019050919050565b60006020820190508181036000830152614b2f81614af3565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b6000614b92602a8361391c565b9150614b9d82614b36565b604082019050919050565b60006020820190508181036000830152614bc181614b85565b9050919050565b60008160601b9050919050565b6000614be082614bc8565b9050919050565b6000614bf282614bd5565b9050919050565b614c0a614c0582613a45565b614be7565b82525050565b60008160f81b9050919050565b6000614c2882614c10565b9050919050565b6000614c3a82614c1d565b9050919050565b614c52614c4d826138a7565b614c2f565b82525050565b6000819050919050565b614c73614c6e826138dd565b614c58565b82525050565b6000614c858287614bf9565b601482019150614c958286614bf9565b601482019150614ca58285614c41565b600182019150614cb58284614c62565b60208201915081905095945050505050565b7f424150433a20696e76616c6964207369676e6174757265000000000000000000600082015250565b6000614cfd60178361391c565b9150614d0882614cc7565b602082019050919050565b60006020820190508181036000830152614d2c81614cf0565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000614d8f602f8361391c565b9150614d9a82614d33565b604082019050919050565b60006020820190508181036000830152614dbe81614d82565b9050919050565b600081905092915050565b6000614ddb82613911565b614de58185614dc5565b9350614df581856020860161392d565b80840191505092915050565b6000614e0d8285614dd0565b9150614e198284614dd0565b91508190509392505050565b6000614e318287614bf9565b601482019150614e418286614bf9565b601482019150614e518285614c62565b602082019150614e618284614c62565b60208201915081905095945050505050565b6000614e7e82613a45565b9050919050565b614e8e81614e73565b8114614e9957600080fd5b50565b600081519050614eab81614e85565b92915050565b600060208284031215614ec757614ec6613818565b5b6000614ed584828501614e9c565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614f3a60268361391c565b9150614f4582614ede565b604082019050919050565b60006020820190508181036000830152614f6981614f2d565b9050919050565b7f424150433a2063616e74206c6f636b207468656d73656c766573000000000000600082015250565b6000614fa6601a8361391c565b9150614fb182614f70565b602082019050919050565b60006020820190508181036000830152614fd581614f99565b9050919050565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000615038602c8361391c565b915061504382614fdc565b604082019050919050565b600060208201905081810360008301526150678161502b565b9050919050565b7f424150433a206f776e6572206973206c6f636b656420666f72207472616e736660008201527f6572730000000000000000000000000000000000000000000000000000000000602082015250565b60006150ca60238361391c565b91506150d58261506e565b604082019050919050565b600060208201905081810360008301526150f9816150bd565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061513660208361391c565b915061514182615100565b602082019050919050565b6000602082019050818103600083015261516581615129565b9050919050565b7f424150433a2063616e7420756e6c6f636b20746869732077616c6c6574000000600082015250565b60006151a2601d8361391c565b91506151ad8261516c565b602082019050919050565b600060208201905081810360008301526151d181615195565b9050919050565b7f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960008201527f6e697469616c697a696e67000000000000000000000000000000000000000000602082015250565b6000615234602b8361391c565b915061523f826151d8565b604082019050919050565b6000602082019050818103600083015261526381615227565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b60006152a060198361391c565b91506152ab8261526a565b602082019050919050565b600060208201905081810360008301526152cf81615293565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b600061533260328361391c565b915061533d826152d6565b604082019050919050565b6000602082019050818103600083015261536181615325565b9050919050565b6000615373826138dd565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036153a5576153a461442d565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006153ea826138dd565b91506153f5836138dd565b925082615405576154046153b0565b5b828204905092915050565b600061541b826138dd565b9150615426836138dd565b925082615436576154356153b0565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f424150433a20616c7265616479206c6f636b6564000000000000000000000000600082015250565b60006154a660148361391c565b91506154b182615470565b602082019050919050565b600060208201905081810360008301526154d581615499565b9050919050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b600061553860258361391c565b9150615543826154dc565b604082019050919050565b600060208201905081810360008301526155678161552b565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b60006155ca60248361391c565b91506155d58261556e565b604082019050919050565b600060208201905081810360008301526155f9816155bd565b9050919050565b7f4552433732313a2063616e2774207472616e73666572207468656d73656c6600600082015250565b6000615636601f8361391c565b915061564182615600565b602082019050919050565b6000602082019050818103600083015261566581615629565b9050919050565b7f424150433a20746f6b656e2063616e2774206265207472616e73666572726564600082015250565b60006156a260208361391c565b91506156ad8261566c565b602082019050919050565b600060208201905081810360008301526156d181615695565b9050919050565b60006156e382613ba4565b91506156ee83613ba4565b9250828210156157015761570061442d565b5b828203905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b6000615742601c83614dc5565b915061574d8261570c565b601c82019050919050565b6000819050919050565b6000819050919050565b61577d61577882615758565b615762565b82525050565b600061578e82615735565b915061579a828461576c565b60208201915081905092915050565b600081519050919050565b600082825260208201905092915050565b60006157d0826157a9565b6157da81856157b4565b93506157ea81856020860161392d565b6157f381613960565b840191505092915050565b60006080820190506158136000830187613a57565b6158206020830186613a57565b61582d60408301856138e7565b818103606083015261583f81846157c5565b905095945050505050565b6000815190506158598161384e565b92915050565b60006020828403121561587557615874613818565b5b60006158838482850161584a565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b60006158f160188361391c565b91506158fc826158bb565b602082019050919050565b60006020820190508181036000830152615920816158e4565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b600061595d601f8361391c565b915061596882615927565b602082019050919050565b6000602082019050818103600083015261598c81615950565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b60006159ef60228361391c565b91506159fa82615993565b604082019050919050565b60006020820190508181036000830152615a1e816159e2565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000615a8160228361391c565b9150615a8c82615a25565b604082019050919050565b60006020820190508181036000830152615ab081615a74565b9050919050565b615ac081615758565b82525050565b6000608082019050615adb6000830187615ab7565b615ae86020830186613b7a565b615af56040830185615ab7565b615b026060830184615ab7565b9594505050505056fea264697066735822122017bf961e91daab9297a4ad60d01ea315a0d8ea88b995bcc6503f775e58f5673c64736f6c634300080f0033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.