Address Details
contract
0xB8e38D2b8f8F4Fa075D903009aa80b1B99193196
- Contract Name
- gameItems
- Creator
- 0x3e89ab–96ea29 at 0x583ce6–a62928
- Balance
- 0 CELO ( )
- Locked CELO Balance
- 0.00 CELO
- Voting CELO Balance
- 0.00 CELO
- Pending Unlocked Gold
- 0.00 CELO
- Tokens
-
Fetching tokens...
- Transactions
- 0 Transactions
- Transfers
- 0 Transfers
- Gas Used
- Fetching gas used...
- Last Balance Update
- 17603852
This contract has been verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- gameItems
- Optimization enabled
- false
- Compiler version
- v0.8.18+commit.87f61d96
- EVM Version
- paris
- Verified at
- 2023-05-06T16:28:39.943095Z
thirdweb.sol
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { ERC1155Base } from "@thirdweb-dev/contracts/base/ERC1155Base.sol"; contract gameItems{ ERC1155Base baseContract; address public custodian; address public newCustodian; event custodyTransferInitiated (address currentCustodian, address newCustodian); event custodyTransferCompleted (address custodian); constructor ( string memory _name, string memory _symbol, address _royaltyRecipient, uint128 _royaltyBps ) { baseContract = new ERC1155Base(_name, _symbol, _royaltyRecipient, _royaltyBps); baseContract.setOperatorRestriction(false); // the OperatorFilterToggle contract handles the emit operation here baseContract.setOwner(address(this)); // Ownable contract handles the emit as well custodian = msg.sender; //call the first mint so mintTo can work later on baseContract.mintTo(custodian, type(uint).max, "ECSTASY ARMOR X1.0.0", 1); } modifier onlyCustodian() { require(msg.sender == custodian, "ERR: NOT CUSTODIAN"); _; } //Custodian change function intiateCustodyTransfer(address _newCustodian) external onlyCustodian{ require(_newCustodian != address(0), "ERR: ZERO ADDRESS"); newCustodian = _newCustodian; emit custodyTransferInitiated(custodian, newCustodian); } function acceptCustody() external { require(msg.sender == newCustodian, "ERR: NOT NEW CUSTODIAN"); custodian = newCustodian; newCustodian = address(0); emit custodyTransferCompleted(custodian); } //Returns the owner of the base contract function getOwner() external view returns(address) { return baseContract.owner(); } function reward(address to, bool newCollection, uint tokenId, string memory uri, uint amount) external onlyCustodian { require(bytes(uri).length > 0, "ERR: EMPTY STRING!"); if(newCollection){ baseContract.mintTo(to, type(uint256).max, uri, amount); }else{ baseContract.mintTo(to, tokenId, uri, amount); } } function balanceOf (address _address, uint _id) external view returns (uint) { return baseContract.balanceOf(_address, _id); } function batchBalanceOf (address[] calldata _address, uint[] calldata _id) external view returns (uint[] memory) { return baseContract.balanceOfBatch(_address, _id); } //Royalty details function setRoyaltyInfo(uint tokenId, address royaltyRecipient, uint royaltyBps) external onlyCustodian{ baseContract.setRoyaltyInfoForToken(tokenId, royaltyRecipient, royaltyBps); // add an emit statement here } function getRoyaltyInfo(uint tokenId) external view returns (address, uint) { return baseContract.getRoyaltyInfoForToken(tokenId); } function calculateRoyalty (uint tokenId, uint salePrice) external view returns (uint) { ( , uint royaltyValue) = baseContract.royaltyInfo(tokenId, salePrice); return royaltyValue; } //MetaData function getName() external view returns (string memory) { return baseContract.name(); } function getSymbol() external view returns (string memory) { return baseContract.symbol(); } function getURI(uint tokenId) external view returns (string memory){ return baseContract.uri(tokenId); } function totalSupply(uint tokenId) external view returns (uint) { return baseContract.totalSupply(tokenId); } }
/_thirdweb-dev/contracts/base/ERC1155Base.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; /// @author thirdweb import { ERC1155 } from "../eip/ERC1155.sol"; import "../extension/ContractMetadata.sol"; import "../extension/Multicall.sol"; import "../extension/Ownable.sol"; import "../extension/Royalty.sol"; import "../extension/BatchMintMetadata.sol"; import "../extension/DefaultOperatorFilterer.sol"; import "../lib/TWStrings.sol"; /** * The `ERC1155Base` smart contract implements the ERC1155 NFT standard. * It includes the following additions to standard ERC1155 logic: * * - Ability to mint NFTs via the provided `mintTo` and `batchMintTo` functions. * * - Contract metadata for royalty support on platforms such as OpenSea that use * off-chain information to distribute roaylties. * * - Ownership of the contract, with the ability to restrict certain functions to * only be called by the contract's owner. * * - Multicall capability to perform multiple actions atomically * * - EIP 2981 compliance for royalty support on NFT marketplaces. */ contract ERC1155Base is ERC1155, ContractMetadata, Ownable, Royalty, Multicall, BatchMintMetadata, DefaultOperatorFilterer { using TWStrings for uint256; /*////////////////////////////////////////////////////////////// State variables //////////////////////////////////////////////////////////////*/ /// @dev The tokenId of the next NFT to mint. uint256 internal nextTokenIdToMint_; /*////////////////////////////////////////////////////////////// Mappings //////////////////////////////////////////////////////////////*/ /** * @notice Returns the total supply of NFTs of a given tokenId * @dev Mapping from tokenId => total circulating supply of NFTs of that tokenId. */ mapping(uint256 => uint256) public totalSupply; /*////////////////////////////////////////////////////////////// Constructor //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, address _royaltyRecipient, uint128 _royaltyBps ) ERC1155(_name, _symbol) { _setupOwner(msg.sender); _setupDefaultRoyaltyInfo(_royaltyRecipient, _royaltyBps); _setOperatorRestriction(true); } /*////////////////////////////////////////////////////////////// Overriden metadata logic //////////////////////////////////////////////////////////////*/ /// @notice Returns the metadata URI for the given tokenId. function uri(uint256 _tokenId) public view virtual override returns (string memory) { string memory uriForToken = _uri[_tokenId]; if (bytes(uriForToken).length > 0) { return uriForToken; } string memory batchUri = _getBaseURI(_tokenId); return string(abi.encodePacked(batchUri, _tokenId.toString())); } /*////////////////////////////////////////////////////////////// Mint / burn logic //////////////////////////////////////////////////////////////*/ /** * @notice Lets an authorized address mint NFTs to a recipient. * @dev - The logic in the `_canMint` function determines whether the caller is authorized to mint NFTs. * - If `_tokenId == type(uint256).max` a new NFT at tokenId `nextTokenIdToMint` is minted. If the given * `tokenId < nextTokenIdToMint`, then additional supply of an existing NFT is being minted. * * @param _to The recipient of the NFTs to mint. * @param _tokenId The tokenId of the NFT to mint. * @param _tokenURI The full metadata URI for the NFTs minted (if a new NFT is being minted). * @param _amount The amount of the same NFT to mint. */ function mintTo( address _to, uint256 _tokenId, string memory _tokenURI, uint256 _amount ) public virtual { require(_canMint(), "Not authorized to mint."); uint256 tokenIdToMint; uint256 nextIdToMint = nextTokenIdToMint(); if (_tokenId == type(uint256).max) { tokenIdToMint = nextIdToMint; nextTokenIdToMint_ += 1; _setTokenURI(nextIdToMint, _tokenURI); } else { require(_tokenId < nextIdToMint, "invalid id"); tokenIdToMint = _tokenId; } _mint(_to, tokenIdToMint, _amount, ""); } /** * @notice Lets an authorized address mint multiple NEW NFTs at once to a recipient. * @dev The logic in the `_canMint` function determines whether the caller is authorized to mint NFTs. * If `_tokenIds[i] == type(uint256).max` a new NFT at tokenId `nextTokenIdToMint` is minted. If the given * `tokenIds[i] < nextTokenIdToMint`, then additional supply of an existing NFT is minted. * The metadata for each new NFT is stored at `baseURI/{tokenID of NFT}` * * @param _to The recipient of the NFT to mint. * @param _tokenIds The tokenIds of the NFTs to mint. * @param _amounts The amounts of each NFT to mint. * @param _baseURI The baseURI for the `n` number of NFTs minted. The metadata for each NFT is `baseURI/tokenId` */ function batchMintTo( address _to, uint256[] memory _tokenIds, uint256[] memory _amounts, string memory _baseURI ) public virtual { require(_canMint(), "Not authorized to mint."); require(_amounts.length > 0, "Minting zero tokens."); require(_tokenIds.length == _amounts.length, "Length mismatch."); uint256 nextIdToMint = nextTokenIdToMint(); uint256 startNextIdToMint = nextIdToMint; uint256 numOfNewNFTs; for (uint256 i = 0; i < _tokenIds.length; i += 1) { if (_tokenIds[i] == type(uint256).max) { _tokenIds[i] = nextIdToMint; nextIdToMint += 1; numOfNewNFTs += 1; } else { require(_tokenIds[i] < nextIdToMint, "invalid id"); } } if (numOfNewNFTs > 0) { _batchMintMetadata(startNextIdToMint, numOfNewNFTs, _baseURI); } nextTokenIdToMint_ = nextIdToMint; _mintBatch(_to, _tokenIds, _amounts, ""); } /** * @notice Lets an owner or approved operator burn NFTs of the given tokenId. * * @param _owner The owner of the NFT to burn. * @param _tokenId The tokenId of the NFT to burn. * @param _amount The amount of the NFT to burn. */ function burn( address _owner, uint256 _tokenId, uint256 _amount ) external virtual { address caller = msg.sender; require(caller == _owner || isApprovedForAll[_owner][caller], "Unapproved caller"); require(balanceOf[_owner][_tokenId] >= _amount, "Not enough tokens owned"); _burn(_owner, _tokenId, _amount); } /** * @notice Lets an owner or approved operator burn NFTs of the given tokenIds. * * @param _owner The owner of the NFTs to burn. * @param _tokenIds The tokenIds of the NFTs to burn. * @param _amounts The amounts of the NFTs to burn. */ function burnBatch( address _owner, uint256[] memory _tokenIds, uint256[] memory _amounts ) external virtual { address caller = msg.sender; require(caller == _owner || isApprovedForAll[_owner][caller], "Unapproved caller"); require(_tokenIds.length == _amounts.length, "Length mismatch"); for (uint256 i = 0; i < _tokenIds.length; i += 1) { require(balanceOf[_owner][_tokenIds[i]] >= _amounts[i], "Not enough tokens owned"); } _burnBatch(_owner, _tokenIds, _amounts); } /*////////////////////////////////////////////////////////////// ERC165 Logic //////////////////////////////////////////////////////////////*/ /// @notice Returns whether this contract supports the given interface. function supportsInterface(bytes4 interfaceId) public view virtual override(ERC1155, IERC165) returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155 interfaceId == 0x0e89341c || // ERC165 Interface ID for ERC1155MetadataURI interfaceId == type(IERC2981).interfaceId; // ERC165 ID for ERC2981 } /*////////////////////////////////////////////////////////////// View functions //////////////////////////////////////////////////////////////*/ /// @notice The tokenId assigned to the next new NFT to be minted. function nextTokenIdToMint() public view virtual returns (uint256) { return nextTokenIdToMint_; } /*////////////////////////////////////////////////////////////// ERC-1155 overrides //////////////////////////////////////////////////////////////*/ /// @dev See {ERC1155-setApprovalForAll} function setApprovalForAll(address operator, bool approved) public virtual override(ERC1155) onlyAllowedOperatorApproval(operator) { super.setApprovalForAll(operator, approved); } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public virtual override(ERC1155) onlyAllowedOperator(from) { super.safeTransferFrom(from, to, id, amount, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override(ERC1155) onlyAllowedOperator(from) { super.safeBatchTransferFrom(from, to, ids, amounts, data); } /*////////////////////////////////////////////////////////////// Internal (overrideable) functions //////////////////////////////////////////////////////////////*/ /// @dev Returns whether contract metadata can be set in the given execution context. function _canSetContractURI() internal view virtual override returns (bool) { return msg.sender == owner(); } /// @dev Returns whether a token can be minted in the given execution context. function _canMint() internal view virtual returns (bool) { return msg.sender == owner(); } /// @dev Returns whether owner can be set in the given execution context. function _canSetOwner() internal view virtual override returns (bool) { return msg.sender == owner(); } /// @dev Returns whether royalty info can be set in the given execution context. function _canSetRoyaltyInfo() internal view virtual override returns (bool) { return msg.sender == owner(); } /// @dev Returns whether operator restriction can be set in the given execution context. function _canSetOperatorRestriction() internal virtual override returns (bool) { return msg.sender == owner(); } /// @dev Runs before every token transfer / mint / burn. function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual override { super._beforeTokenTransfer(operator, from, to, ids, amounts, data); if (from == address(0)) { for (uint256 i = 0; i < ids.length; ++i) { totalSupply[ids[i]] += amounts[i]; } } if (to == address(0)) { for (uint256 i = 0; i < ids.length; ++i) { totalSupply[ids[i]] -= amounts[i]; } } } }
/_thirdweb-dev/contracts/eip/ERC1155.sol
// SPDX-License-Identifier: Apache 2.0 pragma solidity ^0.8.0; import "./interface/IERC1155.sol"; import "./interface/IERC1155Metadata.sol"; import "./interface/IERC1155Receiver.sol"; contract ERC1155 is IERC1155, IERC1155Metadata { /*////////////////////////////////////////////////////////////// State variables //////////////////////////////////////////////////////////////*/ string public name; string public symbol; /*////////////////////////////////////////////////////////////// Mappings //////////////////////////////////////////////////////////////*/ mapping(address => mapping(uint256 => uint256)) public balanceOf; mapping(address => mapping(address => bool)) public isApprovedForAll; mapping(uint256 => string) internal _uri; /*////////////////////////////////////////////////////////////// Constructor //////////////////////////////////////////////////////////////*/ constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } /*////////////////////////////////////////////////////////////// View functions //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155 interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI } function uri(uint256 tokenId) public view virtual override returns (string memory) { return _uri[tokenId]; } function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view virtual override returns (uint256[] memory) { require(accounts.length == ids.length, "LENGTH_MISMATCH"); uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf[accounts[i]][ids[i]]; } return batchBalances; } /*////////////////////////////////////////////////////////////// ERC1155 logic //////////////////////////////////////////////////////////////*/ function setApprovalForAll(address operator, bool approved) public virtual override { address owner = msg.sender; require(owner != operator, "APPROVING_SELF"); isApprovedForAll[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public virtual override { require(from == msg.sender || isApprovedForAll[from][msg.sender], "!OWNER_OR_APPROVED"); _safeTransferFrom(from, to, id, amount, data); } function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override { require(from == msg.sender || isApprovedForAll[from][msg.sender], "!OWNER_OR_APPROVED"); _safeBatchTransferFrom(from, to, ids, amounts, data); } /*////////////////////////////////////////////////////////////// Internal logic //////////////////////////////////////////////////////////////*/ function _safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "TO_ZERO_ADDR"); address operator = msg.sender; _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data); uint256 fromBalance = balanceOf[from][id]; require(fromBalance >= amount, "INSUFFICIENT_BAL"); unchecked { balanceOf[from][id] = fromBalance - amount; } balanceOf[to][id] += amount; emit TransferSingle(operator, from, to, id, amount); _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); } function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(ids.length == amounts.length, "LENGTH_MISMATCH"); require(to != address(0), "TO_ZERO_ADDR"); address operator = msg.sender; _beforeTokenTransfer(operator, from, to, ids, amounts, data); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = balanceOf[from][id]; require(fromBalance >= amount, "INSUFFICIENT_BAL"); unchecked { balanceOf[from][id] = fromBalance - amount; } balanceOf[to][id] += amount; } emit TransferBatch(operator, from, to, ids, amounts); _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); } function _setTokenURI(uint256 tokenId, string memory newuri) internal virtual { _uri[tokenId] = newuri; } function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "TO_ZERO_ADDR"); address operator = msg.sender; _beforeTokenTransfer(operator, address(0), to, _asSingletonArray(id), _asSingletonArray(amount), data); balanceOf[to][id] += amount; emit TransferSingle(operator, address(0), to, id, amount); _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data); } function _mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(to != address(0), "TO_ZERO_ADDR"); require(ids.length == amounts.length, "LENGTH_MISMATCH"); address operator = msg.sender; _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); for (uint256 i = 0; i < ids.length; i++) { balanceOf[to][ids[i]] += amounts[i]; } emit TransferBatch(operator, address(0), to, ids, amounts); _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data); } function _burn( address from, uint256 id, uint256 amount ) internal virtual { require(from != address(0), "FROM_ZERO_ADDR"); address operator = msg.sender; _beforeTokenTransfer(operator, from, address(0), _asSingletonArray(id), _asSingletonArray(amount), ""); uint256 fromBalance = balanceOf[from][id]; require(fromBalance >= amount, "INSUFFICIENT_BAL"); unchecked { balanceOf[from][id] = fromBalance - amount; } emit TransferSingle(operator, from, address(0), id, amount); } function _burnBatch( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { require(from != address(0), "FROM_ZERO_ADDR"); require(ids.length == amounts.length, "LENGTH_MISMATCH"); address operator = msg.sender; _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); for (uint256 i = 0; i < ids.length; i++) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = balanceOf[from][id]; require(fromBalance >= amount, "INSUFFICIENT_BAL"); unchecked { balanceOf[from][id] = fromBalance - amount; } } emit TransferBatch(operator, from, address(0), ids, amounts); } function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 amount, bytes memory data ) private { if (to.code.length > 0) { try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { if (response != IERC1155Receiver.onERC1155Received.selector) { revert("TOKENS_REJECTED"); } } catch Error(string memory reason) { revert(reason); } catch { revert("!ERC1155RECEIVER"); } } } function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { if (to.code.length > 0) { try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( bytes4 response ) { if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { revert("TOKENS_REJECTED"); } } catch Error(string memory reason) { revert(reason); } catch { revert("!ERC1155RECEIVER"); } } } function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); array[0] = element; return array; } }
/_thirdweb-dev/contracts/eip/interface/IERC1155.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; /** @title ERC-1155 Multi Token Standard @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md Note: The ERC-165 identifier for this interface is 0xd9b67a26. */ interface IERC1155 { /** @dev Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard). The `_operator` argument MUST be msg.sender. The `_from` argument MUST be the address of the holder whose balance is decreased. The `_to` argument MUST be the address of the recipient whose balance is increased. The `_id` argument MUST be the token type being transferred. The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by. When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). */ event TransferSingle( address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value ); /** @dev Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard). The `_operator` argument MUST be msg.sender. The `_from` argument MUST be the address of the holder whose balance is decreased. The `_to` argument MUST be the address of the recipient whose balance is increased. The `_ids` argument MUST be the list of tokens being transferred. The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in _ids) the holder balance is decreased by and match what the recipient balance is increased by. When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). */ event TransferBatch( address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values ); /** @dev MUST emit when approval for a second party/operator address to manage all tokens for an owner address is enabled or disabled (absense of an event assumes disabled). */ event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); /** @dev MUST emit when the URI is updated for a token ID. URIs are defined in RFC 3986. The URI MUST point a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema". */ event URI(string _value, uint256 indexed _id); /** @notice Transfers `_value` amount of an `_id` from the `_from` address to the `_to` address specified (with safety call). @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard). MUST revert if `_to` is the zero address. MUST revert if balance of holder for token `_id` is lower than the `_value` sent. MUST revert on any other error. MUST emit the `TransferSingle` event to reflect the balance change (see "Safe Transfer Rules" section of the standard). After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). @param _from Source address @param _to Target address @param _id ID of the token type @param _value Transfer amount @param _data Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to` */ function safeTransferFrom( address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data ) external; /** @notice Transfers `_values` amount(s) of `_ids` from the `_from` address to the `_to` address specified (with safety call). @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard). MUST revert if `_to` is the zero address. MUST revert if length of `_ids` is not the same as length of `_values`. MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient. MUST revert on any other error. MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "Safe Transfer Rules" section of the standard). Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc). After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). @param _from Source address @param _to Target address @param _ids IDs of each token type (order and length must match _values array) @param _values Transfer amounts per token type (order and length must match _ids array) @param _data Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to` */ function safeBatchTransferFrom( address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data ) external; /** @notice Get the balance of an account's Tokens. @param _owner The address of the token holder @param _id ID of the Token @return The _owner's balance of the Token type requested */ function balanceOf(address _owner, uint256 _id) external view returns (uint256); /** @notice Get the balance of multiple account/token pairs @param _owners The addresses of the token holders @param _ids ID of the Tokens @return The _owner's balance of the Token types requested (i.e. balance for each (owner, id) pair) */ function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory); /** @notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens. @dev MUST emit the ApprovalForAll event on success. @param _operator Address to add to the set of authorized operators @param _approved True if the operator is approved, false to revoke approval */ function setApprovalForAll(address _operator, bool _approved) external; /** @notice Queries the approval status of an operator for a given owner. @param _owner The owner of the Tokens @param _operator Address of authorized operator @return True if the operator is approved, false if not */ function isApprovedForAll(address _owner, address _operator) external view returns (bool); }
/_thirdweb-dev/contracts/eip/interface/IERC1155Metadata.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; /** Note: The ERC-165 identifier for this interface is 0x0e89341c. */ interface IERC1155Metadata { /** @notice A distinct Uniform Resource Identifier (URI) for a given token. @dev URIs are defined in RFC 3986. The URI may point to a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema". @return URI string */ function uri(uint256 _id) external view returns (string memory); }
/_thirdweb-dev/contracts/eip/interface/IERC1155Receiver.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
/_thirdweb-dev/contracts/eip/interface/IERC165.sol
// 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 * [EIP](https://eips.ethereum.org/EIPS/eip-165). * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * 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); }
/_thirdweb-dev/contracts/eip/interface/IERC2981.sol
// SPDX-License-Identifier: Apache 2.0 pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be payed in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
/_thirdweb-dev/contracts/extension/BatchMintMetadata.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; /// @author thirdweb /** * @title Batch-mint Metadata * @notice The `BatchMintMetadata` is a contract extension for any base NFT contract. It lets the smart contract * using this extension set metadata for `n` number of NFTs all at once. This is enabled by storing a single * base URI for a batch of `n` NFTs, where the metadata for each NFT in a relevant batch is `baseURI/tokenId`. */ contract BatchMintMetadata { /// @dev Largest tokenId of each batch of tokens with the same baseURI. uint256[] private batchIds; /// @dev Mapping from id of a batch of tokens => to base URI for the respective batch of tokens. mapping(uint256 => string) private baseURI; /** * @notice Returns the count of batches of NFTs. * @dev Each batch of tokens has an in ID and an associated `baseURI`. * See {batchIds}. */ function getBaseURICount() public view returns (uint256) { return batchIds.length; } /** * @notice Returns the ID for the batch of tokens the given tokenId belongs to. * @dev See {getBaseURICount}. * @param _index ID of a token. */ function getBatchIdAtIndex(uint256 _index) public view returns (uint256) { if (_index >= getBaseURICount()) { revert("Invalid index"); } return batchIds[_index]; } /// @dev Returns the id for the batch of tokens the given tokenId belongs to. function _getBatchId(uint256 _tokenId) internal view returns (uint256 batchId, uint256 index) { uint256 numOfTokenBatches = getBaseURICount(); uint256[] memory indices = batchIds; for (uint256 i = 0; i < numOfTokenBatches; i += 1) { if (_tokenId < indices[i]) { index = i; batchId = indices[i]; return (batchId, index); } } revert("Invalid tokenId"); } /// @dev Returns the baseURI for a token. The intended metadata URI for the token is baseURI + tokenId. function _getBaseURI(uint256 _tokenId) internal view returns (string memory) { uint256 numOfTokenBatches = getBaseURICount(); uint256[] memory indices = batchIds; for (uint256 i = 0; i < numOfTokenBatches; i += 1) { if (_tokenId < indices[i]) { return baseURI[indices[i]]; } } revert("Invalid tokenId"); } /// @dev Sets the base URI for the batch of tokens with the given batchId. function _setBaseURI(uint256 _batchId, string memory _baseURI) internal { baseURI[_batchId] = _baseURI; } /// @dev Mints a batch of tokenIds and associates a common baseURI to all those Ids. function _batchMintMetadata( uint256 _startId, uint256 _amountToMint, string memory _baseURIForTokens ) internal returns (uint256 nextTokenIdToMint, uint256 batchId) { batchId = _startId + _amountToMint; nextTokenIdToMint = batchId; batchIds.push(batchId); baseURI[batchId] = _baseURIForTokens; } }
/_thirdweb-dev/contracts/extension/ContractMetadata.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; /// @author thirdweb import "./interface/IContractMetadata.sol"; /** * @title Contract Metadata * @notice Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI * for you contract. * Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea. */ abstract contract ContractMetadata is IContractMetadata { /// @notice Returns the contract metadata URI. string public override contractURI; /** * @notice Lets a contract admin set the URI for contract-level metadata. * @dev Caller should be authorized to setup contractURI, e.g. contract admin. * See {_canSetContractURI}. * Emits {ContractURIUpdated Event}. * * @param _uri keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE") */ function setContractURI(string memory _uri) external override { if (!_canSetContractURI()) { revert("Not authorized"); } _setupContractURI(_uri); } /// @dev Lets a contract admin set the URI for contract-level metadata. function _setupContractURI(string memory _uri) internal { string memory prevURI = contractURI; contractURI = _uri; emit ContractURIUpdated(prevURI, _uri); } /// @dev Returns whether contract metadata can be set in the given execution context. function _canSetContractURI() internal view virtual returns (bool); }
/_thirdweb-dev/contracts/extension/DefaultOperatorFilterer.sol
// SPDX-License-Identifier: Apache 2.0 pragma solidity ^0.8.0; /// @author thirdweb import { OperatorFilterer } from "./OperatorFilterer.sol"; /** * @title DefaultOperatorFilterer * @notice Inherits from OperatorFilterer and automatically subscribes to the default OpenSea subscription. */ abstract contract DefaultOperatorFilterer is OperatorFilterer { address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6); constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {} function subscribeToRegistry(address _subscription) external { require(_canSetOperatorRestriction(), "Not authorized to subscribe to registry."); _register(_subscription, true); } }
/_thirdweb-dev/contracts/extension/Multicall.sol
// SPDX-License-Identifier: Apache 2.0 pragma solidity ^0.8.0; /// @author thirdweb import "../lib/TWAddress.sol"; import "./interface/IMulticall.sol"; /** * @dev Provides a function to batch together multiple calls in a single external call. * * _Available since v4.1._ */ contract Multicall is IMulticall { /** * @notice Receives and executes a batch of function calls on this contract. * @dev Receives and executes a batch of function calls on this contract. * * @param data The bytes data that makes up the batch of function calls to execute. * @return results The bytes data that makes up the result of the batch of function calls executed. */ function multicall(bytes[] calldata data) external virtual override returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { results[i] = TWAddress.functionDelegateCall(address(this), data[i]); } return results; } }
/_thirdweb-dev/contracts/extension/OperatorFilterToggle.sol
// SPDX-License-Identifier: Apache 2.0 pragma solidity ^0.8.0; /// @author thirdweb import "./interface/IOperatorFilterToggle.sol"; abstract contract OperatorFilterToggle is IOperatorFilterToggle { bool public operatorRestriction; function setOperatorRestriction(bool _restriction) external { require(_canSetOperatorRestriction(), "Not authorized to set operator restriction."); _setOperatorRestriction(_restriction); } function _setOperatorRestriction(bool _restriction) internal { operatorRestriction = _restriction; emit OperatorRestriction(_restriction); } function _canSetOperatorRestriction() internal virtual returns (bool); }
/_thirdweb-dev/contracts/extension/OperatorFilterer.sol
// SPDX-License-Identifier: Apache 2.0 pragma solidity ^0.8.0; /// @author thirdweb import "./interface/IOperatorFilterRegistry.sol"; import "./OperatorFilterToggle.sol"; /** * @title OperatorFilterer * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another * registrant's entries in the OperatorFilterRegistry. * @dev This smart contract is meant to be inherited by token contracts so they can use the following: * - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods. * - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods. */ abstract contract OperatorFilterer is OperatorFilterToggle { error OperatorNotAllowed(address operator); IOperatorFilterRegistry public constant OPERATOR_FILTER_REGISTRY = IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E); constructor(address subscriptionOrRegistrantToCopy, bool subscribe) { // If an inheriting token contract is deployed to a network without the registry deployed, the modifier // will not revert, but the contract will need to be registered with the registry once it is deployed in // order for the modifier to filter addresses. _register(subscriptionOrRegistrantToCopy, subscribe); } modifier onlyAllowedOperator(address from) virtual { // Allow spending tokens from addresses with balance // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred // from an EOA. if (from != msg.sender) { _checkFilterOperator(msg.sender); } _; } modifier onlyAllowedOperatorApproval(address operator) virtual { _checkFilterOperator(operator); _; } function _checkFilterOperator(address operator) internal view virtual { // Check registry code length to facilitate testing in environments without a deployed registry. if (operatorRestriction) { if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) { if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) { revert OperatorNotAllowed(operator); } } } } function _register(address subscriptionOrRegistrantToCopy, bool subscribe) internal { // Is the registry deployed? if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) { // Is the subscription contract deployed? if (address(subscriptionOrRegistrantToCopy).code.length > 0) { // Do we want to subscribe? if (subscribe) { OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy); } else { OPERATOR_FILTER_REGISTRY.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy); } } else { OPERATOR_FILTER_REGISTRY.register(address(this)); } } } }
/_thirdweb-dev/contracts/extension/Ownable.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; /// @author thirdweb import "./interface/IOwnable.sol"; /** * @title Ownable * @notice Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading * who the 'owner' of the inheriting smart contract is, and lets the inheriting contract perform conditional logic that uses * information about who the contract's owner is. */ abstract contract Ownable is IOwnable { /// @dev Owner of the contract (purpose: OpenSea compatibility) address private _owner; /// @dev Reverts if caller is not the owner. modifier onlyOwner() { if (msg.sender != _owner) { revert("Not authorized"); } _; } /** * @notice Returns the owner of the contract. */ function owner() public view override returns (address) { return _owner; } /** * @notice Lets an authorized wallet set a new owner for the contract. * @param _newOwner The address to set as the new owner of the contract. */ function setOwner(address _newOwner) external override { if (!_canSetOwner()) { revert("Not authorized"); } _setupOwner(_newOwner); } /// @dev Lets a contract admin set a new owner for the contract. The new owner must be a contract admin. function _setupOwner(address _newOwner) internal { address _prevOwner = _owner; _owner = _newOwner; emit OwnerUpdated(_prevOwner, _newOwner); } /// @dev Returns whether owner can be set in the given execution context. function _canSetOwner() internal view virtual returns (bool); }
/_thirdweb-dev/contracts/extension/Royalty.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; /// @author thirdweb import "./interface/IRoyalty.sol"; /** * @title Royalty * @notice Thirdweb's `Royalty` is a contract extension to be used with any base contract. It exposes functions for setting and reading * the recipient of royalty fee and the royalty fee basis points, and lets the inheriting contract perform conditional logic * that uses information about royalty fees, if desired. * * @dev The `Royalty` contract is ERC2981 compliant. */ abstract contract Royalty is IRoyalty { /// @dev The (default) address that receives all royalty value. address private royaltyRecipient; /// @dev The (default) % of a sale to take as royalty (in basis points). uint16 private royaltyBps; /// @dev Token ID => royalty recipient and bps for token mapping(uint256 => RoyaltyInfo) private royaltyInfoForToken; /** * @notice View royalty info for a given token and sale price. * @dev Returns royalty amount and recipient for `tokenId` and `salePrice`. * @param tokenId The tokenID of the NFT for which to query royalty info. * @param salePrice Sale price of the token. * * @return receiver Address of royalty recipient account. * @return royaltyAmount Royalty amount calculated at current royaltyBps value. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view virtual override returns (address receiver, uint256 royaltyAmount) { (address recipient, uint256 bps) = getRoyaltyInfoForToken(tokenId); receiver = recipient; royaltyAmount = (salePrice * bps) / 10_000; } /** * @notice View royalty info for a given token. * @dev Returns royalty recipient and bps for `_tokenId`. * @param _tokenId The tokenID of the NFT for which to query royalty info. */ function getRoyaltyInfoForToken(uint256 _tokenId) public view override returns (address, uint16) { RoyaltyInfo memory royaltyForToken = royaltyInfoForToken[_tokenId]; return royaltyForToken.recipient == address(0) ? (royaltyRecipient, uint16(royaltyBps)) : (royaltyForToken.recipient, uint16(royaltyForToken.bps)); } /** * @notice Returns the defualt royalty recipient and BPS for this contract's NFTs. */ function getDefaultRoyaltyInfo() external view override returns (address, uint16) { return (royaltyRecipient, uint16(royaltyBps)); } /** * @notice Updates default royalty recipient and bps. * @dev Caller should be authorized to set royalty info. * See {_canSetRoyaltyInfo}. * Emits {DefaultRoyalty Event}; See {_setupDefaultRoyaltyInfo}. * * @param _royaltyRecipient Address to be set as default royalty recipient. * @param _royaltyBps Updated royalty bps. */ function setDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) external override { if (!_canSetRoyaltyInfo()) { revert("Not authorized"); } _setupDefaultRoyaltyInfo(_royaltyRecipient, _royaltyBps); } /// @dev Lets a contract admin update the default royalty recipient and bps. function _setupDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) internal { if (_royaltyBps > 10_000) { revert("Exceeds max bps"); } royaltyRecipient = _royaltyRecipient; royaltyBps = uint16(_royaltyBps); emit DefaultRoyalty(_royaltyRecipient, _royaltyBps); } /** * @notice Updates default royalty recipient and bps for a particular token. * @dev Sets royalty info for `_tokenId`. Caller should be authorized to set royalty info. * See {_canSetRoyaltyInfo}. * Emits {RoyaltyForToken Event}; See {_setupRoyaltyInfoForToken}. * * @param _recipient Address to be set as royalty recipient for given token Id. * @param _bps Updated royalty bps for the token Id. */ function setRoyaltyInfoForToken( uint256 _tokenId, address _recipient, uint256 _bps ) external override { if (!_canSetRoyaltyInfo()) { revert("Not authorized"); } _setupRoyaltyInfoForToken(_tokenId, _recipient, _bps); } /// @dev Lets a contract admin set the royalty recipient and bps for a particular token Id. function _setupRoyaltyInfoForToken( uint256 _tokenId, address _recipient, uint256 _bps ) internal { if (_bps > 10_000) { revert("Exceeds max bps"); } royaltyInfoForToken[_tokenId] = RoyaltyInfo({ recipient: _recipient, bps: _bps }); emit RoyaltyForToken(_tokenId, _recipient, _bps); } /// @dev Returns whether royalty info can be set in the given execution context. function _canSetRoyaltyInfo() internal view virtual returns (bool); }
/_thirdweb-dev/contracts/extension/interface/IContractMetadata.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; /// @author thirdweb /** * Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI * for you contract. * * Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea. */ interface IContractMetadata { /// @dev Returns the metadata URI of the contract. function contractURI() external view returns (string memory); /** * @dev Sets contract URI for the storefront-level metadata of the contract. * Only module admin can call this function. */ function setContractURI(string calldata _uri) external; /// @dev Emitted when the contract URI is updated. event ContractURIUpdated(string prevURI, string newURI); }
/_thirdweb-dev/contracts/extension/interface/IMulticall.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author thirdweb /** * @dev Provides a function to batch together multiple calls in a single external call. * * _Available since v4.1._ */ interface IMulticall { /** * @dev Receives and executes a batch of function calls on this contract. */ function multicall(bytes[] calldata data) external returns (bytes[] memory results); }
/_thirdweb-dev/contracts/extension/interface/IOperatorFilterRegistry.sol
// SPDX-License-Identifier: Apache 2.0 pragma solidity ^0.8.0; /// @author thirdweb interface IOperatorFilterRegistry { function isOperatorAllowed(address registrant, address operator) external view returns (bool); function register(address registrant) external; function registerAndSubscribe(address registrant, address subscription) external; function registerAndCopyEntries(address registrant, address registrantToCopy) external; function unregister(address addr) external; function updateOperator( address registrant, address operator, bool filtered ) external; function updateOperators( address registrant, address[] calldata operators, bool filtered ) external; function updateCodeHash( address registrant, bytes32 codehash, bool filtered ) external; function updateCodeHashes( address registrant, bytes32[] calldata codeHashes, bool filtered ) external; function subscribe(address registrant, address registrantToSubscribe) external; function unsubscribe(address registrant, bool copyExistingEntries) external; function subscriptionOf(address addr) external returns (address registrant); function subscribers(address registrant) external returns (address[] memory); function subscriberAt(address registrant, uint256 index) external returns (address); function copyEntriesOf(address registrant, address registrantToCopy) external; function isOperatorFiltered(address registrant, address operator) external returns (bool); function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool); function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool); function filteredOperators(address addr) external returns (address[] memory); function filteredCodeHashes(address addr) external returns (bytes32[] memory); function filteredOperatorAt(address registrant, uint256 index) external returns (address); function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32); function isRegistered(address addr) external returns (bool); function codeHashOf(address addr) external returns (bytes32); }
/_thirdweb-dev/contracts/extension/interface/IOperatorFilterToggle.sol
// SPDX-License-Identifier: Apache 2.0 pragma solidity ^0.8.0; /// @author thirdweb interface IOperatorFilterToggle { event OperatorRestriction(bool restriction); function operatorRestriction() external view returns (bool); function setOperatorRestriction(bool restriction) external; }
/_thirdweb-dev/contracts/extension/interface/IOwnable.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; /// @author thirdweb /** * Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading * who the 'owner' of the inheriting smart contract is, and lets the inheriting contract perform conditional logic that uses * information about who the contract's owner is. */ interface IOwnable { /// @dev Returns the owner of the contract. function owner() external view returns (address); /// @dev Lets a module admin set a new owner for the contract. The new owner must be a module admin. function setOwner(address _newOwner) external; /// @dev Emitted when a new Owner is set. event OwnerUpdated(address indexed prevOwner, address indexed newOwner); }
/_thirdweb-dev/contracts/extension/interface/IRoyalty.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; /// @author thirdweb import "../../eip/interface/IERC2981.sol"; /** * Thirdweb's `Royalty` is a contract extension to be used with any base contract. It exposes functions for setting and reading * the recipient of royalty fee and the royalty fee basis points, and lets the inheriting contract perform conditional logic * that uses information about royalty fees, if desired. * * The `Royalty` contract is ERC2981 compliant. */ interface IRoyalty is IERC2981 { struct RoyaltyInfo { address recipient; uint256 bps; } /// @dev Returns the royalty recipient and fee bps. function getDefaultRoyaltyInfo() external view returns (address, uint16); /// @dev Lets a module admin update the royalty bps and recipient. function setDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) external; /// @dev Lets a module admin set the royalty recipient for a particular token Id. function setRoyaltyInfoForToken( uint256 tokenId, address recipient, uint256 bps ) external; /// @dev Returns the royalty recipient for a particular token Id. function getRoyaltyInfoForToken(uint256 tokenId) external view returns (address, uint16); /// @dev Emitted when royalty info is updated. event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps); /// @dev Emitted when royalty recipient for tokenId is set event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, uint256 royaltyBps); }
/_thirdweb-dev/contracts/lib/TWAddress.sol
// SPDX-License-Identifier: Apache 2.0 pragma solidity ^0.8.0; /// @author thirdweb /** * @dev Collection of functions related to the address type */ library TWAddress { /** * @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. * * [EIP1884](https://eips.ethereum.org/EIPS/eip-1884) 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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
/_thirdweb-dev/contracts/lib/TWStrings.sol
// SPDX-License-Identifier: Apache 2.0 pragma solidity ^0.8.0; /// @author thirdweb /** * @dev String operations. */ library TWStrings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"string","name":"_name","internalType":"string"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"address","name":"_royaltyRecipient","internalType":"address"},{"type":"uint128","name":"_royaltyBps","internalType":"uint128"}]},{"type":"event","name":"custodyTransferCompleted","inputs":[{"type":"address","name":"custodian","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"custodyTransferInitiated","inputs":[{"type":"address","name":"currentCustodian","internalType":"address","indexed":false},{"type":"address","name":"newCustodian","internalType":"address","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptCustody","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"_address","internalType":"address"},{"type":"uint256","name":"_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"batchBalanceOf","inputs":[{"type":"address[]","name":"_address","internalType":"address[]"},{"type":"uint256[]","name":"_id","internalType":"uint256[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"calculateRoyalty","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"salePrice","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"custodian","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getName","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getOwner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getRoyaltyInfo","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getSymbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getURI","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"intiateCustodyTransfer","inputs":[{"type":"address","name":"_newCustodian","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"newCustodian","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"reward","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"bool","name":"newCollection","internalType":"bool"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"string","name":"uri","internalType":"string"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRoyaltyInfo","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"address","name":"royaltyRecipient","internalType":"address"},{"type":"uint256","name":"royaltyBps","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]}]
Contract Creation Code
0x60806040523480156200001157600080fd5b50604051620092c0380380620092c0833981810160405281019062000037919062000548565b838383836040516200004990620002f5565b62000058949392919062000677565b604051809103906000f08015801562000075573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166332f0cd6460006040518263ffffffff1660e01b8152600401620001119190620006ef565b600060405180830381600087803b1580156200012c57600080fd5b505af115801562000141573d6000803e3d6000fd5b5050505060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166313af4035306040518263ffffffff1660e01b8152600401620001a091906200070c565b600060405180830381600087803b158015620001bb57600080fd5b505af1158015620001d0573d6000803e3d6000fd5b5050505033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b03f4528600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60016040518463ffffffff1660e01b8152600401620002b793929190620007e1565b600060405180830381600087803b158015620002d257600080fd5b505af1158015620002e7573d6000803e3d6000fd5b505050505050505062000833565b616c7a806200264683390190565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200036c8262000321565b810181811067ffffffffffffffff821117156200038e576200038d62000332565b5b80604052505050565b6000620003a362000303565b9050620003b1828262000361565b919050565b600067ffffffffffffffff821115620003d457620003d362000332565b5b620003df8262000321565b9050602081019050919050565b60005b838110156200040c578082015181840152602081019050620003ef565b60008484015250505050565b60006200042f6200042984620003b6565b62000397565b9050828152602081018484840111156200044e576200044d6200031c565b5b6200045b848285620003ec565b509392505050565b600082601f8301126200047b576200047a62000317565b5b81516200048d84826020860162000418565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620004c38262000496565b9050919050565b620004d581620004b6565b8114620004e157600080fd5b50565b600081519050620004f581620004ca565b92915050565b60006fffffffffffffffffffffffffffffffff82169050919050565b6200052281620004fb565b81146200052e57600080fd5b50565b600081519050620005428162000517565b92915050565b600080600080608085870312156200056557620005646200030d565b5b600085015167ffffffffffffffff81111562000586576200058562000312565b5b620005948782880162000463565b945050602085015167ffffffffffffffff811115620005b857620005b762000312565b5b620005c68782880162000463565b9350506040620005d987828801620004e4565b9250506060620005ec8782880162000531565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b60006200062182620005f8565b6200062d818562000603565b93506200063f818560208601620003ec565b6200064a8162000321565b840191505092915050565b6200066081620004b6565b82525050565b6200067181620004fb565b82525050565b6000608082019050818103600083015262000693818762000614565b90508181036020830152620006a9818662000614565b9050620006ba604083018562000655565b620006c9606083018462000666565b95945050505050565b60008115159050919050565b620006e981620006d2565b82525050565b6000602082019050620007066000830184620006de565b92915050565b600060208201905062000723600083018462000655565b92915050565b6000819050919050565b6200073e8162000729565b82525050565b7f454353544153592041524d4f522058312e302e30000000000000000000000000600082015250565b60006200077c60148362000603565b9150620007898262000744565b602082019050919050565b6000819050919050565b6000819050919050565b6000620007c9620007c3620007bd8462000794565b6200079e565b62000729565b9050919050565b620007db81620007a8565b82525050565b6000608082019050620007f8600083018662000655565b62000807602083018562000733565b81810360408301526200081a816200076d565b90506200082b6060830184620007d0565b949350505050565b611e0380620008436000396000f3fe608060405234801561001057600080fd5b50600436106100f45760003560e01c8063816ac99411610097578063b3634a6711610066578063b3634a6714610285578063b76c632b1461028f578063bd85b039146102c0578063cdaa045a146102f0576100f4565b8063816ac994146101ff578063893d20e81461021b5780638e1b72cc14610239578063b0708a3514610255576100f4565b80631a853094116100d35780631a853094146101655780631aa347dc146101955780631f8f14b6146101c5578063375b74c3146101e1576100f4565b8062fdd58e146100f9578063150704011461012957806317d7de7c14610147575b600080fd5b610113600480360381019061010e9190611066565b61030e565b60405161012091906110b5565b60405180910390f35b6101316103b4565b60405161013e9190611160565b60405180910390f35b61014f61044f565b60405161015c9190611160565b60405180910390f35b61017f600480360381019061017a919061123d565b6104ea565b60405161018c919061137c565b60405180910390f35b6101af60048036038101906101aa919061139e565b61059b565b6040516101bc9190611160565b60405180910390f35b6101df60048036038101906101da91906113cb565b610643565b005b6101e9610803565b6040516101f69190611407565b60405180910390f35b6102196004803603810190610214919061158a565b610829565b005b610223610a52565b6040516102309190611407565b60405180910390f35b610253600480360381019061024e9190611621565b610ae9565b005b61026f600480360381019061026a9190611674565b610c0d565b60405161027c91906110b5565b60405180910390f35b61028d610cb8565b005b6102a960048036038101906102a4919061139e565b610e48565b6040516102b79291906116b4565b60405180910390f35b6102da60048036038101906102d5919061139e565b610ef4565b6040516102e791906110b5565b60405180910390f35b6102f8610f98565b6040516103059190611407565b60405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1662fdd58e84846040518363ffffffff1660e01b815260040161036b9291906116b4565b602060405180830381865afa158015610388573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ac91906116f2565b905092915050565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610421573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061044a919061178f565b905090565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156104bc573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906104e5919061178f565b905090565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634e1273f4868686866040518563ffffffff1660e01b815260040161054b9493929190611905565b600060405180830381865afa158015610568573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906105919190611a03565b9050949350505050565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630e89341c836040518263ffffffff1660e01b81526004016105f691906110b5565b600060405180830381865afa158015610613573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061063c919061178f565b9050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106ca90611a98565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610742576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161073990611b04565b60405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fc65f9e2a8610d566a872935180ace6377b1e3fe410bcd2d72a6b703e81025133600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516107f8929190611b24565b60405180910390a150565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108b090611a98565b60405180910390fd5b60008251116108fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108f490611b99565b60405180910390fd5b83156109b95760008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b03f4528867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85856040518563ffffffff1660e01b81526004016109829493929190611bb9565b600060405180830381600087803b15801561099c57600080fd5b505af11580156109b0573d6000803e3d6000fd5b50505050610a4b565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b03f4528868585856040518563ffffffff1660e01b8152600401610a189493929190611bb9565b600060405180830381600087803b158015610a3257600080fd5b505af1158015610a46573d6000803e3d6000fd5b505050505b5050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ac0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae49190611c1a565b905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7090611a98565b60405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639bcf7a158484846040518463ffffffff1660e01b8152600401610bd693929190611c47565b600060405180830381600087803b158015610bf057600080fd5b505af1158015610c04573d6000803e3d6000fd5b50505050505050565b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632a55205a85856040518363ffffffff1660e01b8152600401610c6b929190611c7e565b6040805180830381865afa158015610c87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cab9190611ca7565b9150508091505092915050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3f90611d33565b60405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f22080e9eb6b5ce589cb46f5ffa4e1f070b144980f17689a5a43dfb481d5c83a3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051610e3e9190611407565b60405180910390a1565b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634cc157df846040518263ffffffff1660e01b8152600401610ea491906110b5565b6040805180830381865afa158015610ec0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee49190611d8d565b8061ffff16905091509150915091565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bd85b039836040518263ffffffff1660e01b8152600401610f5091906110b5565b602060405180830381865afa158015610f6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9191906116f2565b9050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610ffd82610fd2565b9050919050565b61100d81610ff2565b811461101857600080fd5b50565b60008135905061102a81611004565b92915050565b6000819050919050565b61104381611030565b811461104e57600080fd5b50565b6000813590506110608161103a565b92915050565b6000806040838503121561107d5761107c610fc8565b5b600061108b8582860161101b565b925050602061109c85828601611051565b9150509250929050565b6110af81611030565b82525050565b60006020820190506110ca60008301846110a6565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561110a5780820151818401526020810190506110ef565b60008484015250505050565b6000601f19601f8301169050919050565b6000611132826110d0565b61113c81856110db565b935061114c8185602086016110ec565b61115581611116565b840191505092915050565b6000602082019050818103600083015261117a8184611127565b905092915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126111a7576111a6611182565b5b8235905067ffffffffffffffff8111156111c4576111c3611187565b5b6020830191508360208202830111156111e0576111df61118c565b5b9250929050565b60008083601f8401126111fd576111fc611182565b5b8235905067ffffffffffffffff81111561121a57611219611187565b5b6020830191508360208202830111156112365761123561118c565b5b9250929050565b6000806000806040858703121561125757611256610fc8565b5b600085013567ffffffffffffffff81111561127557611274610fcd565b5b61128187828801611191565b9450945050602085013567ffffffffffffffff8111156112a4576112a3610fcd565b5b6112b0878288016111e7565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6112f381611030565b82525050565b600061130583836112ea565b60208301905092915050565b6000602082019050919050565b6000611329826112be565b61133381856112c9565b935061133e836112da565b8060005b8381101561136f57815161135688826112f9565b975061136183611311565b925050600181019050611342565b5085935050505092915050565b60006020820190508181036000830152611396818461131e565b905092915050565b6000602082840312156113b4576113b3610fc8565b5b60006113c284828501611051565b91505092915050565b6000602082840312156113e1576113e0610fc8565b5b60006113ef8482850161101b565b91505092915050565b61140181610ff2565b82525050565b600060208201905061141c60008301846113f8565b92915050565b60008115159050919050565b61143781611422565b811461144257600080fd5b50565b6000813590506114548161142e565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61149782611116565b810181811067ffffffffffffffff821117156114b6576114b561145f565b5b80604052505050565b60006114c9610fbe565b90506114d5828261148e565b919050565b600067ffffffffffffffff8211156114f5576114f461145f565b5b6114fe82611116565b9050602081019050919050565b82818337600083830152505050565b600061152d611528846114da565b6114bf565b9050828152602081018484840111156115495761154861145a565b5b61155484828561150b565b509392505050565b600082601f83011261157157611570611182565b5b813561158184826020860161151a565b91505092915050565b600080600080600060a086880312156115a6576115a5610fc8565b5b60006115b48882890161101b565b95505060206115c588828901611445565b94505060406115d688828901611051565b935050606086013567ffffffffffffffff8111156115f7576115f6610fcd565b5b6116038882890161155c565b925050608061161488828901611051565b9150509295509295909350565b60008060006060848603121561163a57611639610fc8565b5b600061164886828701611051565b93505060206116598682870161101b565b925050604061166a86828701611051565b9150509250925092565b6000806040838503121561168b5761168a610fc8565b5b600061169985828601611051565b92505060206116aa85828601611051565b9150509250929050565b60006040820190506116c960008301856113f8565b6116d660208301846110a6565b9392505050565b6000815190506116ec8161103a565b92915050565b60006020828403121561170857611707610fc8565b5b6000611716848285016116dd565b91505092915050565b600061173261172d846114da565b6114bf565b90508281526020810184848401111561174e5761174d61145a565b5b6117598482856110ec565b509392505050565b600082601f83011261177657611775611182565b5b815161178684826020860161171f565b91505092915050565b6000602082840312156117a5576117a4610fc8565b5b600082015167ffffffffffffffff8111156117c3576117c2610fcd565b5b6117cf84828501611761565b91505092915050565b600082825260208201905092915050565b6000819050919050565b6117fc81610ff2565b82525050565b600061180e83836117f3565b60208301905092915050565b6000611829602084018461101b565b905092915050565b6000602082019050919050565b600061184a83856117d8565b9350611855826117e9565b8060005b8581101561188e5761186b828461181a565b6118758882611802565b975061188083611831565b925050600181019050611859565b5085925050509392505050565b600080fd5b82818337505050565b60006118b583856112c9565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156118e8576118e761189b565b5b6020830292506118f98385846118a0565b82840190509392505050565b6000604082019050818103600083015261192081868861183e565b905081810360208301526119358184866118a9565b905095945050505050565b600067ffffffffffffffff82111561195b5761195a61145f565b5b602082029050602081019050919050565b600061197f61197a84611940565b6114bf565b905080838252602082019050602084028301858111156119a2576119a161118c565b5b835b818110156119cb57806119b788826116dd565b8452602084019350506020810190506119a4565b5050509392505050565b600082601f8301126119ea576119e9611182565b5b81516119fa84826020860161196c565b91505092915050565b600060208284031215611a1957611a18610fc8565b5b600082015167ffffffffffffffff811115611a3757611a36610fcd565b5b611a43848285016119d5565b91505092915050565b7f4552523a204e4f5420435553544f4449414e0000000000000000000000000000600082015250565b6000611a826012836110db565b9150611a8d82611a4c565b602082019050919050565b60006020820190508181036000830152611ab181611a75565b9050919050565b7f4552523a205a45524f2041444452455353000000000000000000000000000000600082015250565b6000611aee6011836110db565b9150611af982611ab8565b602082019050919050565b60006020820190508181036000830152611b1d81611ae1565b9050919050565b6000604082019050611b3960008301856113f8565b611b4660208301846113f8565b9392505050565b7f4552523a20454d50545920535452494e47210000000000000000000000000000600082015250565b6000611b836012836110db565b9150611b8e82611b4d565b602082019050919050565b60006020820190508181036000830152611bb281611b76565b9050919050565b6000608082019050611bce60008301876113f8565b611bdb60208301866110a6565b8181036040830152611bed8185611127565b9050611bfc60608301846110a6565b95945050505050565b600081519050611c1481611004565b92915050565b600060208284031215611c3057611c2f610fc8565b5b6000611c3e84828501611c05565b91505092915050565b6000606082019050611c5c60008301866110a6565b611c6960208301856113f8565b611c7660408301846110a6565b949350505050565b6000604082019050611c9360008301856110a6565b611ca060208301846110a6565b9392505050565b60008060408385031215611cbe57611cbd610fc8565b5b6000611ccc85828601611c05565b9250506020611cdd858286016116dd565b9150509250929050565b7f4552523a204e4f54204e455720435553544f4449414e00000000000000000000600082015250565b6000611d1d6016836110db565b9150611d2882611ce7565b602082019050919050565b60006020820190508181036000830152611d4c81611d10565b9050919050565b600061ffff82169050919050565b611d6a81611d53565b8114611d7557600080fd5b50565b600081519050611d8781611d61565b92915050565b60008060408385031215611da457611da3610fc8565b5b6000611db285828601611c05565b9250506020611dc385828601611d78565b915050925092905056fea264697066735822122034476feec514f45deb07122ae842dbe48c437632a1c663a3b7aa60f42847255064736f6c6343000812003360806040523480156200001157600080fd5b5060405162006c7a38038062006c7a83398181016040528101906200003791906200071b565b733cc6cdda760b79bafa08df41ecfa224f810dceb660018585816000908162000061919062000a16565b50806001908162000073919062000a16565b505050620000888282620000db60201b60201c565b50506200009b33620002c060201b60201c565b620000bf82826fffffffffffffffffffffffffffffffff166200038660201b60201c565b620000d160016200048060201b60201c565b5050505062000c43565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115620002bc5760008273ffffffffffffffffffffffffffffffffffffffff163b11156200023d578015620001b7576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16637d3e3dbe30846040518363ffffffff1660e01b81526004016200017d92919062000b0e565b600060405180830381600087803b1580156200019857600080fd5b505af1158015620001ad573d6000803e3d6000fd5b5050505062000237565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663a0af290330846040518363ffffffff1660e01b81526004016200020292919062000b0e565b600060405180830381600087803b1580156200021d57600080fd5b505af115801562000232573d6000803e3d6000fd5b505050505b620002bb565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16634420e486306040518263ffffffff1660e01b815260040162000286919062000b3b565b600060405180830381600087803b158015620002a157600080fd5b505af1158015620002b6573d6000803e3d6000fd5b505050505b5b5050565b6000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7660405160405180910390a35050565b612710811115620003ce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003c59062000bb9565b60405180910390fd5b81600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600760146101000a81548161ffff021916908361ffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167f90d7ec04bcb8978719414f82e52e4cb651db41d0e6f8cea6118c2191e6183adb8260405162000474919062000bec565b60405180910390a25050565b80600b60006101000a81548160ff0219169083151502179055507f38475885990d8dfe9ca01f0ef160a1b5514426eab9ddbc953a3353410ba7809681604051620004cb919062000c26565b60405180910390a150565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200053f82620004f4565b810181811067ffffffffffffffff8211171562000561576200056062000505565b5b80604052505050565b600062000576620004d6565b905062000584828262000534565b919050565b600067ffffffffffffffff821115620005a757620005a662000505565b5b620005b282620004f4565b9050602081019050919050565b60005b83811015620005df578082015181840152602081019050620005c2565b60008484015250505050565b600062000602620005fc8462000589565b6200056a565b905082815260208101848484011115620006215762000620620004ef565b5b6200062e848285620005bf565b509392505050565b600082601f8301126200064e576200064d620004ea565b5b815162000660848260208601620005eb565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620006968262000669565b9050919050565b620006a88162000689565b8114620006b457600080fd5b50565b600081519050620006c8816200069d565b92915050565b60006fffffffffffffffffffffffffffffffff82169050919050565b620006f581620006ce565b81146200070157600080fd5b50565b6000815190506200071581620006ea565b92915050565b60008060008060808587031215620007385762000737620004e0565b5b600085015167ffffffffffffffff811115620007595762000758620004e5565b5b620007678782880162000636565b945050602085015167ffffffffffffffff8111156200078b576200078a620004e5565b5b620007998782880162000636565b9350506040620007ac87828801620006b7565b9250506060620007bf8782880162000704565b91505092959194509250565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200081e57607f821691505b602082108103620008345762000833620007d6565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026200089e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200085f565b620008aa86836200085f565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620008f7620008f1620008eb84620008c2565b620008cc565b620008c2565b9050919050565b6000819050919050565b6200091383620008d6565b6200092b6200092282620008fe565b8484546200086c565b825550505050565b600090565b6200094262000933565b6200094f81848462000908565b505050565b5b8181101562000977576200096b60008262000938565b60018101905062000955565b5050565b601f821115620009c65762000990816200083a565b6200099b846200084f565b81016020851015620009ab578190505b620009c3620009ba856200084f565b83018262000954565b50505b505050565b600082821c905092915050565b6000620009eb60001984600802620009cb565b1980831691505092915050565b600062000a068383620009d8565b9150826002028217905092915050565b62000a2182620007cb565b67ffffffffffffffff81111562000a3d5762000a3c62000505565b5b62000a49825462000805565b62000a568282856200097b565b600060209050601f83116001811462000a8e576000841562000a79578287015190505b62000a858582620009f8565b86555062000af5565b601f19841662000a9e866200083a565b60005b8281101562000ac85784890151825560018201915060208501945060208101905062000aa1565b8683101562000ae8578489015162000ae4601f891682620009d8565b8355505b6001600288020188555050505b505050505050565b62000b088162000689565b82525050565b600060408201905062000b25600083018562000afd565b62000b34602083018462000afd565b9392505050565b600060208201905062000b52600083018462000afd565b92915050565b600082825260208201905092915050565b7f45786365656473206d6178206270730000000000000000000000000000000000600082015250565b600062000ba1600f8362000b58565b915062000bae8262000b69565b602082019050919050565b6000602082019050818103600083015262000bd48162000b92565b9050919050565b62000be681620008c2565b82525050565b600060208201905062000c03600083018462000bdb565b92915050565b60008115159050919050565b62000c208162000c09565b82525050565b600060208201905062000c3d600083018462000c15565b92915050565b6160278062000c536000396000f3fe608060405234801561001057600080fd5b50600436106101ef5760003560e01c806363b45e2d1161010f578063ac9650d8116100a2578063e8a3d48511610071578063e8a3d485146105cb578063e985e9c5146105e9578063f242432a14610619578063f5298aca14610635576101ef565b8063ac9650d814610530578063b03f452814610560578063b24f2d391461057c578063bd85b0391461059b576101ef565b8063949c09f7116100de578063949c09f7146104be57806395d89b41146104da5780639bcf7a15146104f8578063a22cb46514610514576101ef565b806363b45e2d1461044a5780636b20c454146104685780638da5cb5b14610484578063938e3d7b146104a2576101ef565b806332f0cd64116101875780634e1273f4116101565780634e1273f4146103c4578063504c6e01146103f457806357fd845514610412578063600dd5ea1461042e576101ef565b806332f0cd641461033b5780633b1475a71461035757806341f43434146103755780634cc157df14610393576101ef565b806313af4035116101c357806313af4035146102a25780632419f51b146102be5780632a55205a146102ee5780632eb2c2d61461031f576101ef565b8062fdd58e146101f457806301ffc9a71461022457806306fdde03146102545780630e89341c14610272575b600080fd5b61020e60048036038101906102099190613e12565b610651565b60405161021b9190613e61565b60405180910390f35b61023e60048036038101906102399190613ed4565b610676565b60405161024b9190613f1c565b60405180910390f35b61025c610770565b6040516102699190613fc7565b60405180910390f35b61028c60048036038101906102879190613fe9565b6107fe565b6040516102999190613fc7565b60405180910390f35b6102bc60048036038101906102b79190614016565b6108f4565b005b6102d860048036038101906102d39190613fe9565b610947565b6040516102e59190613e61565b60405180910390f35b61030860048036038101906103039190614043565b6109b8565b604051610316929190614092565b60405180910390f35b610339600480360381019061033491906142b8565b6109f6565b005b610355600480360381019061035091906143b3565b610a49565b005b61035f610a9c565b60405161036c9190613e61565b60405180910390f35b61037d610aa6565b60405161038a919061443f565b60405180910390f35b6103ad60048036038101906103a89190613fe9565b610ab8565b6040516103bb929190614477565b60405180910390f35b6103de60048036038101906103d99190614563565b610bc3565b6040516103eb9190614699565b60405180910390f35b6103fc610d23565b6040516104099190613f1c565b60405180910390f35b61042c60048036038101906104279190614016565b610d36565b005b61044860048036038101906104439190613e12565b610d8b565b005b610452610de0565b60405161045f9190613e61565b60405180910390f35b610482600480360381019061047d91906146bb565b610ded565b005b61048c61102e565b6040516104999190614746565b60405180910390f35b6104bc60048036038101906104b79190614802565b611058565b005b6104d860048036038101906104d3919061484b565b6110ab565b005b6104e26112d4565b6040516104ef9190613fc7565b60405180910390f35b610512600480360381019061050d9190614906565b611362565b005b61052e60048036038101906105299190614959565b6113b9565b005b61054a600480360381019061054591906149f4565b6113d2565b6040516105579190614b58565b60405180910390f35b61057a60048036038101906105759190614b7a565b6114de565b005b6105846115ee565b604051610592929190614477565b60405180910390f35b6105b560048036038101906105b09190613fe9565b61162d565b6040516105c29190613e61565b60405180910390f35b6105d3611645565b6040516105e09190613fc7565b60405180910390f35b61060360048036038101906105fe9190614bfd565b6116d3565b6040516106109190613f1c565b60405180910390f35b610633600480360381019061062e9190614c3d565b611702565b005b61064f600480360381019061064a9190614cd4565b611755565b005b6002602052816000526040600020602052806000526040600020600091509150505481565b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806106d1575063d9b67a2660e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806107015750630e89341c60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061076957507f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b6000805461077d90614d56565b80601f01602080910402602001604051908101604052809291908181526020018280546107a990614d56565b80156107f65780601f106107cb576101008083540402835291602001916107f6565b820191906000526020600020905b8154815290600101906020018083116107d957829003601f168201915b505050505081565b6060600060046000848152602001908152602001600020805461082090614d56565b80601f016020809104026020016040519081016040528092919081815260200182805461084c90614d56565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b505050505090506000815111156108b357809150506108ef565b60006108be846118fd565b9050806108ca85611aa2565b6040516020016108db929190614dc3565b604051602081830303815290604052925050505b919050565b6108fc611c02565b61093b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161093290614e33565b60405180910390fd5b61094481611c3f565b50565b6000610951610de0565b8210610992576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098990614e9f565b60405180910390fd5b600982815481106109a6576109a5614ebf565b5b90600052602060002001549050919050565b6000806000806109c786610ab8565b61ffff169150915081935061271081866109e19190614f1d565b6109eb9190614f8e565b925050509250929050565b843373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610a3457610a3333611d05565b5b610a418686868686611e18565b505050505050565b610a51611f2b565b610a90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a8790615031565b60405180910390fd5b610a9981611f68565b50565b6000600c54905090565b6daaeb6d7670e522a718067333cd4e81565b6000806000600860008581526020019081526020016000206040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820154815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614610b845780600001518160200151610bb9565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600760149054906101000a900461ffff165b9250925050915091565b60608151835114610c09576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c009061509d565b60405180910390fd5b6000835167ffffffffffffffff811115610c2657610c256140c0565b5b604051908082528060200260200182016040528015610c545781602001602082028036833780820191505090505b50905060005b8451811015610d185760026000868381518110610c7a57610c79614ebf565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000858381518110610cd157610cd0614ebf565b5b6020026020010151815260200190815260200160002054828281518110610cfb57610cfa614ebf565b5b60200260200101818152505080610d11906150bd565b9050610c5a565b508091505092915050565b600b60009054906101000a900460ff1681565b610d3e611f2b565b610d7d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7490615177565b60405180910390fd5b610d88816001611fbc565b50565b610d93612190565b610dd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc990614e33565b60405180910390fd5b610ddc82826121cd565b5050565b6000600980549050905090565b60003390508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610eb25750600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610ef1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ee8906151e3565b60405180910390fd5b8151835114610f35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f2c9061524f565b60405180910390fd5b60005b835181101561101c57828181518110610f5457610f53614ebf565b5b6020026020010151600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000868481518110610fb057610faf614ebf565b5b60200260200101518152602001908152602001600020541015611008576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fff906152bb565b60405180910390fd5b60018161101591906152db565b9050610f38565b506110288484846122c2565b50505050565b6000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61106061256d565b61109f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109690614e33565b60405180910390fd5b6110a8816125aa565b50565b6110b3612686565b6110f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110e99061535b565b60405180910390fd5b6000825111611136576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161112d906153c7565b60405180910390fd5b815183511461117a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161117190615433565b60405180910390fd5b6000611184610a9c565b90506000819050600080600090505b8651811015611291577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8782815181106111d0576111cf614ebf565b5b60200260200101510361122057838782815181106111f1576111f0614ebf565b5b60200260200101818152505060018461120a91906152db565b935060018261121991906152db565b915061127d565b8387828151811061123457611233614ebf565b5b60200260200101511061127c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112739061549f565b60405180910390fd5b5b60018161128a91906152db565b9050611193565b5060008111156112a9576112a68282866126c3565b50505b82600c819055506112cb87878760405180602001604052806000815250612729565b50505050505050565b600180546112e190614d56565b80601f016020809104026020016040519081016040528092919081815260200182805461130d90614d56565b801561135a5780601f1061132f5761010080835404028352916020019161135a565b820191906000526020600020905b81548152906001019060200180831161133d57829003601f168201915b505050505081565b61136a612190565b6113a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113a090614e33565b60405180910390fd5b6113b4838383612940565b505050565b816113c381611d05565b6113cd8383612a6b565b505050565b60608282905067ffffffffffffffff8111156113f1576113f06140c0565b5b60405190808252806020026020018201604052801561142457816020015b606081526020019060019003908161140f5790505b50905060005b838390508110156114d7576114a63085858481811061144c5761144b614ebf565b5b905060200281019061145e91906154ce565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612bdc565b8282815181106114b9576114b8614ebf565b5b602002602001018190525080806114cf906150bd565b91505061142a565b5092915050565b6114e6612686565b611525576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151c9061535b565b60405180910390fd5b600080611530610a9c565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8503611585578091506001600c600082825461156f91906152db565b925050819055506115808185612c09565b6115cb565b8085106115c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115be9061549f565b60405180910390fd5b8491505b6115e686838560405180602001604052806000815250612c2e565b505050505050565b600080600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600760149054906101000a900461ffff16915091509091565b600d6020528060005260406000206000915090505481565b6005805461165290614d56565b80601f016020809104026020016040519081016040528092919081815260200182805461167e90614d56565b80156116cb5780601f106116a0576101008083540402835291602001916116cb565b820191906000526020600020905b8154815290600101906020018083116116ae57829003601f168201915b505050505081565b60036020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b843373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146117405761173f33611d05565b5b61174d8686868686612dbd565b505050505050565b60003390508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061181a5750600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b611859576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611850906151e3565b60405180910390fd5b81600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008581526020019081526020016000205410156118ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118e3906152bb565b60405180910390fd5b6118f7848484612ed0565b50505050565b60606000611909610de0565b90506000600980548060200260200160405190810160405280929190818152602001828054801561195957602002820191906000526020600020905b815481526020019060010190808311611945575b5050505050905060005b82811015611a615781818151811061197e5761197d614ebf565b5b6020026020010151851015611a4d57600a60008383815181106119a4576119a3614ebf565b5b6020026020010151815260200190815260200160002080546119c590614d56565b80601f01602080910402602001604051908101604052809291908181526020018280546119f190614d56565b8015611a3e5780601f10611a1357610100808354040283529160200191611a3e565b820191906000526020600020905b815481529060010190602001808311611a2157829003601f168201915b50505050509350505050611a9d565b600181611a5a91906152db565b9050611963565b506040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a949061557d565b60405180910390fd5b919050565b606060008203611ae9576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050611bfd565b600082905060005b60008214611b1b578080611b04906150bd565b915050600a82611b149190614f8e565b9150611af1565b60008167ffffffffffffffff811115611b3757611b366140c0565b5b6040519080825280601f01601f191660200182016040528015611b695781602001600182028036833780820191505090505b5090505b60008514611bf657600182611b82919061559d565b9150600a85611b9191906155d1565b6030611b9d91906152db565b60f81b818381518110611bb357611bb2614ebf565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85611bef9190614f8e565b9450611b6d565b8093505050505b919050565b6000611c0c61102e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7660405160405180910390a35050565b600b60009054906101000a900460ff1615611e155760006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115611e14576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401611d91929190615602565b602060405180830381865afa158015611dae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd29190615640565b611e1357806040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401611e0a9190614746565b60405180910390fd5b5b5b50565b3373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161480611ed85750600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b611f17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f0e906156b9565b60405180910390fd5b611f2485858585856130e7565b5050505050565b6000611f3561102e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b80600b60006101000a81548160ff0219169083151502179055507f38475885990d8dfe9ca01f0ef160a1b5514426eab9ddbc953a3353410ba7809681604051611fb19190613f1c565b60405180910390a150565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561218c5760008273ffffffffffffffffffffffffffffffffffffffff163b1115612111578015612090576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16637d3e3dbe30846040518363ffffffff1660e01b8152600401612059929190615602565b600060405180830381600087803b15801561207357600080fd5b505af1158015612087573d6000803e3d6000fd5b5050505061210c565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663a0af290330846040518363ffffffff1660e01b81526004016120d9929190615602565b600060405180830381600087803b1580156120f357600080fd5b505af1158015612107573d6000803e3d6000fd5b505050505b61218b565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16634420e486306040518263ffffffff1660e01b81526004016121589190614746565b600060405180830381600087803b15801561217257600080fd5b505af1158015612186573d6000803e3d6000fd5b505050505b5b5050565b600061219a61102e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b612710811115612212576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161220990615725565b60405180910390fd5b81600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600760146101000a81548161ffff021916908361ffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167f90d7ec04bcb8978719414f82e52e4cb651db41d0e6f8cea6118c2191e6183adb826040516122b69190613e61565b60405180910390a25050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612331576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161232890615791565b60405180910390fd5b8051825114612375576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161236c9061509d565b60405180910390fd5b6000339050612398818560008686604051806020016040528060008152506133f6565b60005b83518110156124e75760008482815181106123b9576123b8614ebf565b5b6020026020010151905060008483815181106123d8576123d7614ebf565b5b602002602001015190506000600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000205490508181101561247a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612471906157fd565b60405180910390fd5b818103600260008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008581526020019081526020016000208190555050505080806124df906150bd565b91505061239b565b50600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb868660405161255f92919061581d565b60405180910390a450505050565b600061257761102e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6000600580546125b990614d56565b80601f01602080910402602001604051908101604052809291908181526020018280546125e590614d56565b80156126325780601f1061260757610100808354040283529160200191612632565b820191906000526020600020905b81548152906001019060200180831161261557829003601f168201915b50505050509050816005908161264891906159f6565b507fc9c7c3fe08b88b4df9d4d47ef47d2c43d55c025a0ba88ca442580ed9e7348a16818360405161267a929190615ac8565b60405180910390a15050565b600061269061102e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b60008083856126d291906152db565b9050809150600981908060018154018082558091505060019003906000526020600020016000909190919091505582600a6000838152602001908152602001600020908161272091906159f6565b50935093915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612798576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161278f90615b4b565b60405180910390fd5b81518351146127dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127d39061509d565b60405180910390fd5b60003390506127f0816000878787876133f6565b60005b84518110156128aa5783818151811061280f5761280e614ebf565b5b6020026020010151600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600087848151811061286b5761286a614ebf565b5b60200260200101518152602001908152602001600020600082825461289091906152db565b9250508190555080806128a2906150bd565b9150506127f3565b508473ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161292292919061581d565b60405180910390a46129398160008787878761356e565b5050505050565b612710811115612985576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161297c90615725565b60405180910390fd5b60405180604001604052808373ffffffffffffffffffffffffffffffffffffffff168152602001828152506008600085815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101559050508173ffffffffffffffffffffffffffffffffffffffff16837f7365cf4122f072a3365c20d54eff9b38d73c096c28e1892ec8f5b0e403a0f12d83604051612a5e9190613e61565b60405180910390a3505050565b60003390508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612ade576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ad590615bb7565b60405180910390fd5b81600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3184604051612bcf9190613f1c565b60405180910390a3505050565b6060612c018383604051806060016040528060278152602001615fcb60279139613741565b905092915050565b80600460008481526020019081526020016000209081612c2991906159f6565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612c9d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c9490615b4b565b60405180910390fd5b6000339050612cc181600087612cb28861380e565b612cbb8861380e565b876133f6565b82600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008681526020019081526020016000206000828254612d2191906152db565b925050819055508473ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628787604051612d9f929190615bd7565b60405180910390a4612db681600087878787613888565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161480612e7d5750600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b612ebc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eb3906156b9565b60405180910390fd5b612ec98585858585613a5b565b5050505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612f3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f3690615791565b60405180910390fd5b6000339050612f7281856000612f548761380e565b612f5d8761380e565b604051806020016040528060008152506133f6565b6000600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008581526020019081526020016000205490508281101561300a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613001906157fd565b60405180910390fd5b828103600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600086815260200190815260200160002081905550600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6287876040516130d8929190615bd7565b60405180910390a45050505050565b815183511461312b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131229061509d565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361319a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161319190615b4b565b60405180910390fd5b60003390506131ad8187878787876133f6565b60005b84518110156133615760008582815181106131ce576131cd614ebf565b5b6020026020010151905060008583815181106131ed576131ec614ebf565b5b602002602001015190506000600260008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000205490508181101561328f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613286906157fd565b60405180910390fd5b818103600260008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008581526020019081526020016000208190555081600260008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000858152602001908152602001600020600082825461334691906152db565b925050819055505050508061335a906150bd565b90506131b0565b508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516133d892919061581d565b60405180910390a46133ee81878787878761356e565b505050505050565b613404868686868686613cd8565b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036134b55760005b83518110156134b35782818151811061345757613456614ebf565b5b6020026020010151600d600086848151811061347657613475614ebf565b5b60200260200101518152602001908152602001600020600082825461349b91906152db565b92505081905550806134ac906150bd565b905061343b565b505b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036135665760005b83518110156135645782818151811061350857613507614ebf565b5b6020026020010151600d600086848151811061352757613526614ebf565b5b60200260200101518152602001908152602001600020600082825461354c919061559d565b925050819055508061355d906150bd565b90506134ec565b505b505050505050565b60008473ffffffffffffffffffffffffffffffffffffffff163b1115613739578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b81526004016135cf959493929190615c4a565b6020604051808303816000875af192505050801561360b57506040513d601f19601f820116820180604052508101906136089190615cc7565b60015b6136b057613617615d01565b806308c379a003613673575061362b615d23565b806136365750613675565b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161366a9190613fc7565b60405180910390fd5b505b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136a790615dff565b60405180910390fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614613737576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161372e90615e6b565b60405180910390fd5b505b505050505050565b606061374c84613ce0565b61378b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161378290615efd565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516137b39190615f59565b600060405180830381855af49150503d80600081146137ee576040519150601f19603f3d011682016040523d82523d6000602084013e6137f3565b606091505b5091509150613803828286613d03565b925050509392505050565b60606000600167ffffffffffffffff81111561382d5761382c6140c0565b5b60405190808252806020026020018201604052801561385b5781602001602082028036833780820191505090505b509050828160008151811061387357613872614ebf565b5b60200260200101818152505080915050919050565b60008473ffffffffffffffffffffffffffffffffffffffff163b1115613a53578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b81526004016138e9959493929190615f70565b6020604051808303816000875af192505050801561392557506040513d601f19601f820116820180604052508101906139229190615cc7565b60015b6139ca57613931615d01565b806308c379a00361398d5750613945615d23565b80613950575061398f565b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139849190613fc7565b60405180910390fd5b505b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139c190615dff565b60405180910390fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614613a51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613a4890615e6b565b60405180910390fd5b505b505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603613aca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613ac190615b4b565b60405180910390fd5b6000339050613aed818787613ade8861380e565b613ae78861380e565b876133f6565b6000600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600086815260200190815260200160002054905083811015613b85576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b7c906157fd565b60405180910390fd5b838103600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008781526020019081526020016000208190555083600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008781526020019081526020016000206000828254613c3c91906152db565b925050819055508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628888604051613cb9929190615bd7565b60405180910390a4613ccf828888888888613888565b50505050505050565b505050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60608315613d1357829050613d63565b600083511115613d265782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613d5a9190613fc7565b60405180910390fd5b9392505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613da982613d7e565b9050919050565b613db981613d9e565b8114613dc457600080fd5b50565b600081359050613dd681613db0565b92915050565b6000819050919050565b613def81613ddc565b8114613dfa57600080fd5b50565b600081359050613e0c81613de6565b92915050565b60008060408385031215613e2957613e28613d74565b5b6000613e3785828601613dc7565b9250506020613e4885828601613dfd565b9150509250929050565b613e5b81613ddc565b82525050565b6000602082019050613e766000830184613e52565b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613eb181613e7c565b8114613ebc57600080fd5b50565b600081359050613ece81613ea8565b92915050565b600060208284031215613eea57613ee9613d74565b5b6000613ef884828501613ebf565b91505092915050565b60008115159050919050565b613f1681613f01565b82525050565b6000602082019050613f316000830184613f0d565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613f71578082015181840152602081019050613f56565b60008484015250505050565b6000601f19601f8301169050919050565b6000613f9982613f37565b613fa38185613f42565b9350613fb3818560208601613f53565b613fbc81613f7d565b840191505092915050565b60006020820190508181036000830152613fe18184613f8e565b905092915050565b600060208284031215613fff57613ffe613d74565b5b600061400d84828501613dfd565b91505092915050565b60006020828403121561402c5761402b613d74565b5b600061403a84828501613dc7565b91505092915050565b6000806040838503121561405a57614059613d74565b5b600061406885828601613dfd565b925050602061407985828601613dfd565b9150509250929050565b61408c81613d9e565b82525050565b60006040820190506140a76000830185614083565b6140b46020830184613e52565b9392505050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6140f882613f7d565b810181811067ffffffffffffffff82111715614117576141166140c0565b5b80604052505050565b600061412a613d6a565b905061413682826140ef565b919050565b600067ffffffffffffffff821115614156576141556140c0565b5b602082029050602081019050919050565b600080fd5b600061417f61417a8461413b565b614120565b905080838252602082019050602084028301858111156141a2576141a1614167565b5b835b818110156141cb57806141b78882613dfd565b8452602084019350506020810190506141a4565b5050509392505050565b600082601f8301126141ea576141e96140bb565b5b81356141fa84826020860161416c565b91505092915050565b600080fd5b600067ffffffffffffffff821115614223576142226140c0565b5b61422c82613f7d565b9050602081019050919050565b82818337600083830152505050565b600061425b61425684614208565b614120565b90508281526020810184848401111561427757614276614203565b5b614282848285614239565b509392505050565b600082601f83011261429f5761429e6140bb565b5b81356142af848260208601614248565b91505092915050565b600080600080600060a086880312156142d4576142d3613d74565b5b60006142e288828901613dc7565b95505060206142f388828901613dc7565b945050604086013567ffffffffffffffff81111561431457614313613d79565b5b614320888289016141d5565b935050606086013567ffffffffffffffff81111561434157614340613d79565b5b61434d888289016141d5565b925050608086013567ffffffffffffffff81111561436e5761436d613d79565b5b61437a8882890161428a565b9150509295509295909350565b61439081613f01565b811461439b57600080fd5b50565b6000813590506143ad81614387565b92915050565b6000602082840312156143c9576143c8613d74565b5b60006143d78482850161439e565b91505092915050565b6000819050919050565b60006144056144006143fb84613d7e565b6143e0565b613d7e565b9050919050565b6000614417826143ea565b9050919050565b60006144298261440c565b9050919050565b6144398161441e565b82525050565b60006020820190506144546000830184614430565b92915050565b600061ffff82169050919050565b6144718161445a565b82525050565b600060408201905061448c6000830185614083565b6144996020830184614468565b9392505050565b600067ffffffffffffffff8211156144bb576144ba6140c0565b5b602082029050602081019050919050565b60006144df6144da846144a0565b614120565b9050808382526020820190506020840283018581111561450257614501614167565b5b835b8181101561452b57806145178882613dc7565b845260208401935050602081019050614504565b5050509392505050565b600082601f83011261454a576145496140bb565b5b813561455a8482602086016144cc565b91505092915050565b6000806040838503121561457a57614579613d74565b5b600083013567ffffffffffffffff81111561459857614597613d79565b5b6145a485828601614535565b925050602083013567ffffffffffffffff8111156145c5576145c4613d79565b5b6145d1858286016141d5565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61461081613ddc565b82525050565b60006146228383614607565b60208301905092915050565b6000602082019050919050565b6000614646826145db565b61465081856145e6565b935061465b836145f7565b8060005b8381101561468c5781516146738882614616565b975061467e8361462e565b92505060018101905061465f565b5085935050505092915050565b600060208201905081810360008301526146b3818461463b565b905092915050565b6000806000606084860312156146d4576146d3613d74565b5b60006146e286828701613dc7565b935050602084013567ffffffffffffffff81111561470357614702613d79565b5b61470f868287016141d5565b925050604084013567ffffffffffffffff8111156147305761472f613d79565b5b61473c868287016141d5565b9150509250925092565b600060208201905061475b6000830184614083565b92915050565b600067ffffffffffffffff82111561477c5761477b6140c0565b5b61478582613f7d565b9050602081019050919050565b60006147a56147a084614761565b614120565b9050828152602081018484840111156147c1576147c0614203565b5b6147cc848285614239565b509392505050565b600082601f8301126147e9576147e86140bb565b5b81356147f9848260208601614792565b91505092915050565b60006020828403121561481857614817613d74565b5b600082013567ffffffffffffffff81111561483657614835613d79565b5b614842848285016147d4565b91505092915050565b6000806000806080858703121561486557614864613d74565b5b600061487387828801613dc7565b945050602085013567ffffffffffffffff81111561489457614893613d79565b5b6148a0878288016141d5565b935050604085013567ffffffffffffffff8111156148c1576148c0613d79565b5b6148cd878288016141d5565b925050606085013567ffffffffffffffff8111156148ee576148ed613d79565b5b6148fa878288016147d4565b91505092959194509250565b60008060006060848603121561491f5761491e613d74565b5b600061492d86828701613dfd565b935050602061493e86828701613dc7565b925050604061494f86828701613dfd565b9150509250925092565b600080604083850312156149705761496f613d74565b5b600061497e85828601613dc7565b925050602061498f8582860161439e565b9150509250929050565b600080fd5b60008083601f8401126149b4576149b36140bb565b5b8235905067ffffffffffffffff8111156149d1576149d0614999565b5b6020830191508360208202830111156149ed576149ec614167565b5b9250929050565b60008060208385031215614a0b57614a0a613d74565b5b600083013567ffffffffffffffff811115614a2957614a28613d79565b5b614a358582860161499e565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000614a9482614a6d565b614a9e8185614a78565b9350614aae818560208601613f53565b614ab781613f7d565b840191505092915050565b6000614ace8383614a89565b905092915050565b6000602082019050919050565b6000614aee82614a41565b614af88185614a4c565b935083602082028501614b0a85614a5d565b8060005b85811015614b465784840389528151614b278582614ac2565b9450614b3283614ad6565b925060208a01995050600181019050614b0e565b50829750879550505050505092915050565b60006020820190508181036000830152614b728184614ae3565b905092915050565b60008060008060808587031215614b9457614b93613d74565b5b6000614ba287828801613dc7565b9450506020614bb387828801613dfd565b935050604085013567ffffffffffffffff811115614bd457614bd3613d79565b5b614be0878288016147d4565b9250506060614bf187828801613dfd565b91505092959194509250565b60008060408385031215614c1457614c13613d74565b5b6000614c2285828601613dc7565b9250506020614c3385828601613dc7565b9150509250929050565b600080600080600060a08688031215614c5957614c58613d74565b5b6000614c6788828901613dc7565b9550506020614c7888828901613dc7565b9450506040614c8988828901613dfd565b9350506060614c9a88828901613dfd565b925050608086013567ffffffffffffffff811115614cbb57614cba613d79565b5b614cc78882890161428a565b9150509295509295909350565b600080600060608486031215614ced57614cec613d74565b5b6000614cfb86828701613dc7565b9350506020614d0c86828701613dfd565b9250506040614d1d86828701613dfd565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614d6e57607f821691505b602082108103614d8157614d80614d27565b5b50919050565b600081905092915050565b6000614d9d82613f37565b614da78185614d87565b9350614db7818560208601613f53565b80840191505092915050565b6000614dcf8285614d92565b9150614ddb8284614d92565b91508190509392505050565b7f4e6f7420617574686f72697a6564000000000000000000000000000000000000600082015250565b6000614e1d600e83613f42565b9150614e2882614de7565b602082019050919050565b60006020820190508181036000830152614e4c81614e10565b9050919050565b7f496e76616c696420696e64657800000000000000000000000000000000000000600082015250565b6000614e89600d83613f42565b9150614e9482614e53565b602082019050919050565b60006020820190508181036000830152614eb881614e7c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614f2882613ddc565b9150614f3383613ddc565b9250828202614f4181613ddc565b91508282048414831517614f5857614f57614eee565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614f9982613ddc565b9150614fa483613ddc565b925082614fb457614fb3614f5f565b5b828204905092915050565b7f4e6f7420617574686f72697a656420746f20736574206f70657261746f72207260008201527f65737472696374696f6e2e000000000000000000000000000000000000000000602082015250565b600061501b602b83613f42565b915061502682614fbf565b604082019050919050565b6000602082019050818103600083015261504a8161500e565b9050919050565b7f4c454e4754485f4d49534d415443480000000000000000000000000000000000600082015250565b6000615087600f83613f42565b915061509282615051565b602082019050919050565b600060208201905081810360008301526150b68161507a565b9050919050565b60006150c882613ddc565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036150fa576150f9614eee565b5b600182019050919050565b7f4e6f7420617574686f72697a656420746f2073756273637269626520746f207260008201527f656769737472792e000000000000000000000000000000000000000000000000602082015250565b6000615161602883613f42565b915061516c82615105565b604082019050919050565b6000602082019050818103600083015261519081615154565b9050919050565b7f556e617070726f7665642063616c6c6572000000000000000000000000000000600082015250565b60006151cd601183613f42565b91506151d882615197565b602082019050919050565b600060208201905081810360008301526151fc816151c0565b9050919050565b7f4c656e677468206d69736d617463680000000000000000000000000000000000600082015250565b6000615239600f83613f42565b915061524482615203565b602082019050919050565b600060208201905081810360008301526152688161522c565b9050919050565b7f4e6f7420656e6f75676820746f6b656e73206f776e6564000000000000000000600082015250565b60006152a5601783613f42565b91506152b08261526f565b602082019050919050565b600060208201905081810360008301526152d481615298565b9050919050565b60006152e682613ddc565b91506152f183613ddc565b925082820190508082111561530957615308614eee565b5b92915050565b7f4e6f7420617574686f72697a656420746f206d696e742e000000000000000000600082015250565b6000615345601783613f42565b91506153508261530f565b602082019050919050565b6000602082019050818103600083015261537481615338565b9050919050565b7f4d696e74696e67207a65726f20746f6b656e732e000000000000000000000000600082015250565b60006153b1601483613f42565b91506153bc8261537b565b602082019050919050565b600060208201905081810360008301526153e0816153a4565b9050919050565b7f4c656e677468206d69736d617463682e00000000000000000000000000000000600082015250565b600061541d601083613f42565b9150615428826153e7565b602082019050919050565b6000602082019050818103600083015261544c81615410565b9050919050565b7f696e76616c696420696400000000000000000000000000000000000000000000600082015250565b6000615489600a83613f42565b915061549482615453565b602082019050919050565b600060208201905081810360008301526154b88161547c565b9050919050565b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126154eb576154ea6154bf565b5b80840192508235915067ffffffffffffffff82111561550d5761550c6154c4565b5b602083019250600182023603831315615529576155286154c9565b5b509250929050565b7f496e76616c696420746f6b656e49640000000000000000000000000000000000600082015250565b6000615567600f83613f42565b915061557282615531565b602082019050919050565b600060208201905081810360008301526155968161555a565b9050919050565b60006155a882613ddc565b91506155b383613ddc565b92508282039050818111156155cb576155ca614eee565b5b92915050565b60006155dc82613ddc565b91506155e783613ddc565b9250826155f7576155f6614f5f565b5b828206905092915050565b60006040820190506156176000830185614083565b6156246020830184614083565b9392505050565b60008151905061563a81614387565b92915050565b60006020828403121561565657615655613d74565b5b60006156648482850161562b565b91505092915050565b7f214f574e45525f4f525f415050524f5645440000000000000000000000000000600082015250565b60006156a3601283613f42565b91506156ae8261566d565b602082019050919050565b600060208201905081810360008301526156d281615696565b9050919050565b7f45786365656473206d6178206270730000000000000000000000000000000000600082015250565b600061570f600f83613f42565b915061571a826156d9565b602082019050919050565b6000602082019050818103600083015261573e81615702565b9050919050565b7f46524f4d5f5a45524f5f41444452000000000000000000000000000000000000600082015250565b600061577b600e83613f42565b915061578682615745565b602082019050919050565b600060208201905081810360008301526157aa8161576e565b9050919050565b7f494e53554646494349454e545f42414c00000000000000000000000000000000600082015250565b60006157e7601083613f42565b91506157f2826157b1565b602082019050919050565b60006020820190508181036000830152615816816157da565b9050919050565b60006040820190508181036000830152615837818561463b565b9050818103602083015261584b818461463b565b90509392505050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026158b67fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82615879565b6158c08683615879565b95508019841693508086168417925050509392505050565b60006158f36158ee6158e984613ddc565b6143e0565b613ddc565b9050919050565b6000819050919050565b61590d836158d8565b615921615919826158fa565b848454615886565b825550505050565b600090565b615936615929565b615941818484615904565b505050565b5b818110156159655761595a60008261592e565b600181019050615947565b5050565b601f8211156159aa5761597b81615854565b61598484615869565b81016020851015615993578190505b6159a761599f85615869565b830182615946565b50505b505050565b600082821c905092915050565b60006159cd600019846008026159af565b1980831691505092915050565b60006159e683836159bc565b9150826002028217905092915050565b6159ff82613f37565b67ffffffffffffffff811115615a1857615a176140c0565b5b615a228254614d56565b615a2d828285615969565b600060209050601f831160018114615a605760008415615a4e578287015190505b615a5885826159da565b865550615ac0565b601f198416615a6e86615854565b60005b82811015615a9657848901518255600182019150602085019450602081019050615a71565b86831015615ab35784890151615aaf601f8916826159bc565b8355505b6001600288020188555050505b505050505050565b60006040820190508181036000830152615ae28185613f8e565b90508181036020830152615af68184613f8e565b90509392505050565b7f544f5f5a45524f5f414444520000000000000000000000000000000000000000600082015250565b6000615b35600c83613f42565b9150615b4082615aff565b602082019050919050565b60006020820190508181036000830152615b6481615b28565b9050919050565b7f415050524f56494e475f53454c46000000000000000000000000000000000000600082015250565b6000615ba1600e83613f42565b9150615bac82615b6b565b602082019050919050565b60006020820190508181036000830152615bd081615b94565b9050919050565b6000604082019050615bec6000830185613e52565b615bf96020830184613e52565b9392505050565b600082825260208201905092915050565b6000615c1c82614a6d565b615c268185615c00565b9350615c36818560208601613f53565b615c3f81613f7d565b840191505092915050565b600060a082019050615c5f6000830188614083565b615c6c6020830187614083565b8181036040830152615c7e818661463b565b90508181036060830152615c92818561463b565b90508181036080830152615ca68184615c11565b90509695505050505050565b600081519050615cc181613ea8565b92915050565b600060208284031215615cdd57615cdc613d74565b5b6000615ceb84828501615cb2565b91505092915050565b60008160e01c9050919050565b600060033d1115615d205760046000803e615d1d600051615cf4565b90505b90565b600060443d10615db057615d35613d6a565b60043d036004823e80513d602482011167ffffffffffffffff82111715615d5d575050615db0565b808201805167ffffffffffffffff811115615d7b5750505050615db0565b80602083010160043d038501811115615d98575050505050615db0565b615da7826020018501866140ef565b82955050505050505b90565b7f2145524331313535524543454956455200000000000000000000000000000000600082015250565b6000615de9601083613f42565b9150615df482615db3565b602082019050919050565b60006020820190508181036000830152615e1881615ddc565b9050919050565b7f544f4b454e535f52454a45435445440000000000000000000000000000000000600082015250565b6000615e55600f83613f42565b9150615e6082615e1f565b602082019050919050565b60006020820190508181036000830152615e8481615e48565b9050919050565b7f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60008201527f6e74726163740000000000000000000000000000000000000000000000000000602082015250565b6000615ee7602683613f42565b9150615ef282615e8b565b604082019050919050565b60006020820190508181036000830152615f1681615eda565b9050919050565b600081905092915050565b6000615f3382614a6d565b615f3d8185615f1d565b9350615f4d818560208601613f53565b80840191505092915050565b6000615f658284615f28565b915081905092915050565b600060a082019050615f856000830188614083565b615f926020830187614083565b615f9f6040830186613e52565b615fac6060830185613e52565b8181036080830152615fbe8184615c11565b9050969550505050505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201ea17aac8ef68af9bee26fc8140f381715b74493f735fed266dd7db662ef041b64736f6c63430008120033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000005b38da6a701c568545dcfcb03fcb875f56beddc400000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000014454353544153592047414d4520454c454d454e5400000000000000000000000000000000000000000000000000000000000000000000000000000000000000034547450000000000000000000000000000000000000000000000000000000000
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100f45760003560e01c8063816ac99411610097578063b3634a6711610066578063b3634a6714610285578063b76c632b1461028f578063bd85b039146102c0578063cdaa045a146102f0576100f4565b8063816ac994146101ff578063893d20e81461021b5780638e1b72cc14610239578063b0708a3514610255576100f4565b80631a853094116100d35780631a853094146101655780631aa347dc146101955780631f8f14b6146101c5578063375b74c3146101e1576100f4565b8062fdd58e146100f9578063150704011461012957806317d7de7c14610147575b600080fd5b610113600480360381019061010e9190611066565b61030e565b60405161012091906110b5565b60405180910390f35b6101316103b4565b60405161013e9190611160565b60405180910390f35b61014f61044f565b60405161015c9190611160565b60405180910390f35b61017f600480360381019061017a919061123d565b6104ea565b60405161018c919061137c565b60405180910390f35b6101af60048036038101906101aa919061139e565b61059b565b6040516101bc9190611160565b60405180910390f35b6101df60048036038101906101da91906113cb565b610643565b005b6101e9610803565b6040516101f69190611407565b60405180910390f35b6102196004803603810190610214919061158a565b610829565b005b610223610a52565b6040516102309190611407565b60405180910390f35b610253600480360381019061024e9190611621565b610ae9565b005b61026f600480360381019061026a9190611674565b610c0d565b60405161027c91906110b5565b60405180910390f35b61028d610cb8565b005b6102a960048036038101906102a4919061139e565b610e48565b6040516102b79291906116b4565b60405180910390f35b6102da60048036038101906102d5919061139e565b610ef4565b6040516102e791906110b5565b60405180910390f35b6102f8610f98565b6040516103059190611407565b60405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1662fdd58e84846040518363ffffffff1660e01b815260040161036b9291906116b4565b602060405180830381865afa158015610388573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ac91906116f2565b905092915050565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610421573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061044a919061178f565b905090565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156104bc573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906104e5919061178f565b905090565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634e1273f4868686866040518563ffffffff1660e01b815260040161054b9493929190611905565b600060405180830381865afa158015610568573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906105919190611a03565b9050949350505050565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630e89341c836040518263ffffffff1660e01b81526004016105f691906110b5565b600060405180830381865afa158015610613573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061063c919061178f565b9050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106ca90611a98565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610742576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161073990611b04565b60405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fc65f9e2a8610d566a872935180ace6377b1e3fe410bcd2d72a6b703e81025133600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516107f8929190611b24565b60405180910390a150565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108b090611a98565b60405180910390fd5b60008251116108fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108f490611b99565b60405180910390fd5b83156109b95760008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b03f4528867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85856040518563ffffffff1660e01b81526004016109829493929190611bb9565b600060405180830381600087803b15801561099c57600080fd5b505af11580156109b0573d6000803e3d6000fd5b50505050610a4b565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b03f4528868585856040518563ffffffff1660e01b8152600401610a189493929190611bb9565b600060405180830381600087803b158015610a3257600080fd5b505af1158015610a46573d6000803e3d6000fd5b505050505b5050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ac0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae49190611c1a565b905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7090611a98565b60405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639bcf7a158484846040518463ffffffff1660e01b8152600401610bd693929190611c47565b600060405180830381600087803b158015610bf057600080fd5b505af1158015610c04573d6000803e3d6000fd5b50505050505050565b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632a55205a85856040518363ffffffff1660e01b8152600401610c6b929190611c7e565b6040805180830381865afa158015610c87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cab9190611ca7565b9150508091505092915050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3f90611d33565b60405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f22080e9eb6b5ce589cb46f5ffa4e1f070b144980f17689a5a43dfb481d5c83a3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051610e3e9190611407565b60405180910390a1565b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634cc157df846040518263ffffffff1660e01b8152600401610ea491906110b5565b6040805180830381865afa158015610ec0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee49190611d8d565b8061ffff16905091509150915091565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bd85b039836040518263ffffffff1660e01b8152600401610f5091906110b5565b602060405180830381865afa158015610f6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9191906116f2565b9050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610ffd82610fd2565b9050919050565b61100d81610ff2565b811461101857600080fd5b50565b60008135905061102a81611004565b92915050565b6000819050919050565b61104381611030565b811461104e57600080fd5b50565b6000813590506110608161103a565b92915050565b6000806040838503121561107d5761107c610fc8565b5b600061108b8582860161101b565b925050602061109c85828601611051565b9150509250929050565b6110af81611030565b82525050565b60006020820190506110ca60008301846110a6565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561110a5780820151818401526020810190506110ef565b60008484015250505050565b6000601f19601f8301169050919050565b6000611132826110d0565b61113c81856110db565b935061114c8185602086016110ec565b61115581611116565b840191505092915050565b6000602082019050818103600083015261117a8184611127565b905092915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126111a7576111a6611182565b5b8235905067ffffffffffffffff8111156111c4576111c3611187565b5b6020830191508360208202830111156111e0576111df61118c565b5b9250929050565b60008083601f8401126111fd576111fc611182565b5b8235905067ffffffffffffffff81111561121a57611219611187565b5b6020830191508360208202830111156112365761123561118c565b5b9250929050565b6000806000806040858703121561125757611256610fc8565b5b600085013567ffffffffffffffff81111561127557611274610fcd565b5b61128187828801611191565b9450945050602085013567ffffffffffffffff8111156112a4576112a3610fcd565b5b6112b0878288016111e7565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6112f381611030565b82525050565b600061130583836112ea565b60208301905092915050565b6000602082019050919050565b6000611329826112be565b61133381856112c9565b935061133e836112da565b8060005b8381101561136f57815161135688826112f9565b975061136183611311565b925050600181019050611342565b5085935050505092915050565b60006020820190508181036000830152611396818461131e565b905092915050565b6000602082840312156113b4576113b3610fc8565b5b60006113c284828501611051565b91505092915050565b6000602082840312156113e1576113e0610fc8565b5b60006113ef8482850161101b565b91505092915050565b61140181610ff2565b82525050565b600060208201905061141c60008301846113f8565b92915050565b60008115159050919050565b61143781611422565b811461144257600080fd5b50565b6000813590506114548161142e565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61149782611116565b810181811067ffffffffffffffff821117156114b6576114b561145f565b5b80604052505050565b60006114c9610fbe565b90506114d5828261148e565b919050565b600067ffffffffffffffff8211156114f5576114f461145f565b5b6114fe82611116565b9050602081019050919050565b82818337600083830152505050565b600061152d611528846114da565b6114bf565b9050828152602081018484840111156115495761154861145a565b5b61155484828561150b565b509392505050565b600082601f83011261157157611570611182565b5b813561158184826020860161151a565b91505092915050565b600080600080600060a086880312156115a6576115a5610fc8565b5b60006115b48882890161101b565b95505060206115c588828901611445565b94505060406115d688828901611051565b935050606086013567ffffffffffffffff8111156115f7576115f6610fcd565b5b6116038882890161155c565b925050608061161488828901611051565b9150509295509295909350565b60008060006060848603121561163a57611639610fc8565b5b600061164886828701611051565b93505060206116598682870161101b565b925050604061166a86828701611051565b9150509250925092565b6000806040838503121561168b5761168a610fc8565b5b600061169985828601611051565b92505060206116aa85828601611051565b9150509250929050565b60006040820190506116c960008301856113f8565b6116d660208301846110a6565b9392505050565b6000815190506116ec8161103a565b92915050565b60006020828403121561170857611707610fc8565b5b6000611716848285016116dd565b91505092915050565b600061173261172d846114da565b6114bf565b90508281526020810184848401111561174e5761174d61145a565b5b6117598482856110ec565b509392505050565b600082601f83011261177657611775611182565b5b815161178684826020860161171f565b91505092915050565b6000602082840312156117a5576117a4610fc8565b5b600082015167ffffffffffffffff8111156117c3576117c2610fcd565b5b6117cf84828501611761565b91505092915050565b600082825260208201905092915050565b6000819050919050565b6117fc81610ff2565b82525050565b600061180e83836117f3565b60208301905092915050565b6000611829602084018461101b565b905092915050565b6000602082019050919050565b600061184a83856117d8565b9350611855826117e9565b8060005b8581101561188e5761186b828461181a565b6118758882611802565b975061188083611831565b925050600181019050611859565b5085925050509392505050565b600080fd5b82818337505050565b60006118b583856112c9565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156118e8576118e761189b565b5b6020830292506118f98385846118a0565b82840190509392505050565b6000604082019050818103600083015261192081868861183e565b905081810360208301526119358184866118a9565b905095945050505050565b600067ffffffffffffffff82111561195b5761195a61145f565b5b602082029050602081019050919050565b600061197f61197a84611940565b6114bf565b905080838252602082019050602084028301858111156119a2576119a161118c565b5b835b818110156119cb57806119b788826116dd565b8452602084019350506020810190506119a4565b5050509392505050565b600082601f8301126119ea576119e9611182565b5b81516119fa84826020860161196c565b91505092915050565b600060208284031215611a1957611a18610fc8565b5b600082015167ffffffffffffffff811115611a3757611a36610fcd565b5b611a43848285016119d5565b91505092915050565b7f4552523a204e4f5420435553544f4449414e0000000000000000000000000000600082015250565b6000611a826012836110db565b9150611a8d82611a4c565b602082019050919050565b60006020820190508181036000830152611ab181611a75565b9050919050565b7f4552523a205a45524f2041444452455353000000000000000000000000000000600082015250565b6000611aee6011836110db565b9150611af982611ab8565b602082019050919050565b60006020820190508181036000830152611b1d81611ae1565b9050919050565b6000604082019050611b3960008301856113f8565b611b4660208301846113f8565b9392505050565b7f4552523a20454d50545920535452494e47210000000000000000000000000000600082015250565b6000611b836012836110db565b9150611b8e82611b4d565b602082019050919050565b60006020820190508181036000830152611bb281611b76565b9050919050565b6000608082019050611bce60008301876113f8565b611bdb60208301866110a6565b8181036040830152611bed8185611127565b9050611bfc60608301846110a6565b95945050505050565b600081519050611c1481611004565b92915050565b600060208284031215611c3057611c2f610fc8565b5b6000611c3e84828501611c05565b91505092915050565b6000606082019050611c5c60008301866110a6565b611c6960208301856113f8565b611c7660408301846110a6565b949350505050565b6000604082019050611c9360008301856110a6565b611ca060208301846110a6565b9392505050565b60008060408385031215611cbe57611cbd610fc8565b5b6000611ccc85828601611c05565b9250506020611cdd858286016116dd565b9150509250929050565b7f4552523a204e4f54204e455720435553544f4449414e00000000000000000000600082015250565b6000611d1d6016836110db565b9150611d2882611ce7565b602082019050919050565b60006020820190508181036000830152611d4c81611d10565b9050919050565b600061ffff82169050919050565b611d6a81611d53565b8114611d7557600080fd5b50565b600081519050611d8781611d61565b92915050565b60008060408385031215611da457611da3610fc8565b5b6000611db285828601611c05565b9250506020611dc385828601611d78565b915050925092905056fea264697066735822122034476feec514f45deb07122ae842dbe48c437632a1c663a3b7aa60f42847255064736f6c63430008120033