Overview
POL Balance
0 POL
POL Value
$0.00More Info
Private Name Tags
ContractCreator
Sponsored
Loading...
Loading
Contract Name:
RedditCollectibleAvatars
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.8.4; import "@opengsn/contracts/src/BaseRelayRecipient.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts/interfaces/IERC2981.sol"; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "./RedditCollectibleAvatarsRouter.sol"; /** * * An ERC1155-based NFT contract which includes support for partitioned (bucketed) IPFS routes. * * This contract is a standard ERC1155 contract with modifications to make the contract * allow for a dynamically-sized collection of NFTs to be minted on it over a prolonged * period of time. * * These differences are: * * 1. The contact leverages ownership of the contract (OwnableUpgradeable), however it also * allows for the NFT minting method (`mintNFT`) to be only executable via a * `minter` wallet. * * 2. The `uri` mechanism of the contract defers to a sub contract which acts as * a router to determine what IPFS directory CID value will be used for the uri * of the provided tokenId. * * While the behavior of "minting over a prolonged period of time" is something that isn't * common in the crypto space, the intent with this contract is to only allow for minting * to occur until the collection is complete. Once complete, ownership and minting on the * contract will be relinquished. * * * ## How the minting logic works * * The `mintNFT` method works much the same as any public minting function on an ERC721 or * ERC1155 contract. The main difference here is that only the `minter` wallet can execute * this method instead of the `owner` of the contract. The `minter` wallet is a standard * 0x0 address that can be set via the `setMinter()` method and it can be the same as the * owner of the wallet. * * The reason why this contract makes use of a minter/owner split is so that the deployment * and configuration of contract is done via an offline wallet while minting of new NFTs is * done using a wallet that is distributed on the backend. * * * ## How the `uri` assembling works * * With a standard ERC1155 contract, all NFT URI values (which point to their respective * metadata files) are bound to a single URI structure with a consistent domain/path prefix. * This design choice is done as such by ERC1155 to optimize storage of NFT entries within * the contract (since no URL values need to be stored). * * While this feature of ERC1155 works well, it doesn't allow for a collection of NFTs to * be extended without some kind of variable change to the prefix of the `uri`. In other * words, you would need to introduce a setter/getter value to change the IPFS prefix if * new NFT metadata files are introduced into the collection. * * The contract below changes how the `uri` method works by delegating the IPFS CID resolution * logic to a "router" contract. The router contract will execute its own logic given the `ID` * value and return the correct IPFS CID based on what IPFS directory that `ID` entry was * registered. * * See [RedditCollectibleAvatarsRouter.sol] for more info. * */ error RedditCollectibleAvatars__NotMinter(); error RedditCollectibleAvatars__InvalidArg_TokenAndAddressLengthMismatch(); error RedditCollectibleAvatars__InvalidArg_AddressZero(); error RedditCollectibleAvatars__InvalidArg_SellerFeeBasisPoints(uint16 basisPoints); error RedditCollectibleAvatars__AlreadyMinted(uint256 tokenId); error RedditCollectibleAvatars__NotImplemented(); contract RedditCollectibleAvatars is ERC1155Upgradeable, OwnableUpgradeable, BaseRelayRecipient, IERC2981 { using AddressUpgradeable for address; struct RoyaltyInfo { address recipient; uint16 basisPoints; } event RouterAddressUpdated(address current, address previous); event MinterUpdated(address current, address prevMinter, address removedMinter); event PreviousMinterCleared(address removedMinter); event TrustedForwarderUpdated(address current, address previous); event ContractURIUpdated(string current, string previous); event RoyaltiesUpdated(address currentRecipient, uint16 currentBasisPoints, address previousRecipient, uint16 previousBasisPoints); string public override versionRecipient; // required by BaseRelayRecipient /** * Wallet address of the `minter` wallet */ address public minter; /** * Wallet address of the previous `minter` wallet to have no downtime during minter rotation */ address public prevMinter; /** * Reference to the "router contract" that the `uri` method will call * * See [RedditCollectibleAvatarsRouter] for more info. */ RedditCollectibleAvatarsRouter public _router; RoyaltyInfo public royalties; string private _contractURI; // Mapping from token ID to owner mapping(uint256 => address) internal _owners; modifier onlyMinter() { address sender = _msgSender(); if (sender != minter && sender != prevMinter) { revert RedditCollectibleAvatars__NotMinter(); } _; } function initialize(RoyaltyInfo calldata _royalties, address routerAddress, address minterAddress, address owner, address forwarder, string calldata contracturi) public initializer { __ERC1155_init("_"); _updateRoyalties(_royalties); minter = minterAddress; prevMinter = address(0); _setRouterAddress(routerAddress); _updateTrustedForwarder(forwarder); _contractURI = contracturi; OwnableUpgradeable.__Ownable_init(); if (owner != _msgSender()) { OwnableUpgradeable.transferOwnership(owner); } versionRecipient = "1.0.0"; } /** * OZ ERC1155 Function Overrides */ /** * @dev See {IERC1155-balanceOf}. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { require(account != address(0), "ERC1155: balance query for the zero address"); return _owners[id] == account ? 1 : 0; } /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual override { require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); uint256[] memory ids = __asSingletonArray(id); uint256[] memory amounts = __asSingletonArray(amount); _beforeTokenTransfer(operator, from, to, ids, amounts, data); require(_owners[id] == from && amount < 2, "ERC1155: insufficient balance for transfer"); // The ERC1155 spec allows for transferring zero tokens, // but only modify ownership if amount == 1 if (amount == 1) { _owners[id] = to; } emit TransferSingle(operator, from, to, id, amount); _afterTokenTransfer(operator, from, to, ids, amounts, data); __doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); } function __doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 amount, bytes memory data ) internal { if (to.isContract()) { try IERC1155ReceiverUpgradeable(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { if (response != IERC1155ReceiverUpgradeable.onERC1155Received.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non ERC1155Receiver implementer"); } } } function __asSingletonArray(uint256 element) internal pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); array[0] = element; return array; } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual override { require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; require(_owners[id] == from && amount < 2, "ERC1155: insufficient balance for transfer"); // The ERC1155 spec allows for transferring zero tokens, // but only modify ownership if amount == 1 if (amount == 1) { _owners[id] = to; } } emit TransferBatch(operator, from, to, ids, amounts); __doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); } function __doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal { if (to.isContract()) { try IERC1155ReceiverUpgradeable(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( bytes4 response ) { if (response != IERC1155ReceiverUpgradeable.onERC1155BatchReceived.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non ERC1155Receiver implementer"); } } } /** * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint( address to, uint256 id, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); if(_owners[id] != address(0)) { revert RedditCollectibleAvatars__AlreadyMinted(id); } address operator = _msgSender(); _owners[id] = to; emit TransferSingle(operator, address(0), to, id, 1); __doSafeTransferAcceptanceCheck(operator, address(0), to, id, 1, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch( address, uint256[] memory, uint256[] memory, bytes memory ) internal virtual override { revert RedditCollectibleAvatars__NotImplemented(); } /** * @dev Destroys `amount` tokens of token type `id` from `from` * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `amount` tokens of token type `id`. */ function _burn( address, uint256, uint256 ) internal virtual override { revert RedditCollectibleAvatars__NotImplemented(); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Requirements: * * - `ids` and `amounts` must have the same length. */ function _burnBatch( address, uint256[] memory, uint256[] memory ) internal virtual override { revert RedditCollectibleAvatars__NotImplemented(); } /** * IPFS Routing Functions */ function setRouterAddress(address routerAddress) external onlyOwner { _setRouterAddress(routerAddress); } /** * Sets the contract address for the router contract (which is used to deterine the IPFS CID for each ID entry) */ function _setRouterAddress(address routerAddress) internal { if (routerAddress == address(0)){ revert RedditCollectibleAvatars__InvalidArg_AddressZero(); } emit RouterAddressUpdated({current: routerAddress, previous: address(_router)}); _router = RedditCollectibleAvatarsRouter(routerAddress); } /** * Minting Functions */ /** * Mints a NFT on the contract (node that only the `minter` wallet can execute this action) */ function mintNFT(uint256 tokenId, address ownerId) public onlyMinter { _mint(ownerId, tokenId, ""); } /** * Sets (updates) the `minter` wallet address on the contract (note that only the `owner` wallet can execute this action) */ function setMinter(address account) public onlyOwner { if (account == address(0)){ revert RedditCollectibleAvatars__InvalidArg_AddressZero(); } emit MinterUpdated({current: account, prevMinter: minter, removedMinter: prevMinter}); prevMinter = minter; minter = account; } function clearPreviousMinter() public onlyOwner { emit PreviousMinterCleared({removedMinter: prevMinter}); prevMinter = address(0); } /** * Returns a URL for the provided `id` value. * * This method will call the "router" contract to determine what the cid value of the * IPFS url will be for the provided `id` entry. */ function uri(uint256 id) public view override returns (string memory) { string memory cid = _router.lookup(id); return string( abi.encodePacked( "ipfs://", cid, "/", Strings.toString(id), ".json" ) ); } function contractURI() public view returns (string memory) { return _contractURI; } function updateContractURI(string calldata contracturi) external onlyOwner { emit ContractURIUpdated(contracturi, _contractURI); _contractURI = contracturi; } function batchMint(uint256[] calldata tokenIds, address[] calldata ownerIds) public onlyMinter { if (tokenIds.length != ownerIds.length) { revert RedditCollectibleAvatars__InvalidArg_TokenAndAddressLengthMismatch(); } for (uint256 i=0; i < tokenIds.length; ++i) { _mint(ownerIds[i], tokenIds[i], ""); } } function royaltyInfo(uint256, uint256 _salePrice) external view override returns (address receiver, uint256 royaltyAmount) { receiver = royalties.recipient; royaltyAmount = (_salePrice * royalties.basisPoints) / 10000; } function updateRoyalties(RoyaltyInfo calldata _royalties) external onlyOwner { _updateRoyalties(_royalties); } function _updateRoyalties(RoyaltyInfo calldata _royalties) internal { if(_royalties.basisPoints > 10000){ revert RedditCollectibleAvatars__InvalidArg_SellerFeeBasisPoints(_royalties.basisPoints); } emit RoyaltiesUpdated(_royalties.recipient, _royalties.basisPoints, royalties.recipient, royalties.basisPoints); royalties = _royalties; } function updateTrustedForwarder(address forwarder) external onlyOwner { _updateTrustedForwarder(forwarder); } function _updateTrustedForwarder(address forwarder) internal { emit TrustedForwarderUpdated(forwarder, trustedForwarder()); _setTrustedForwarder(forwarder); } function _msgSender() internal view override(BaseRelayRecipient, ContextUpgradeable) returns (address ret) { ret = BaseRelayRecipient._msgSender(); } function _msgData() internal view override(BaseRelayRecipient, ContextUpgradeable) returns (bytes calldata ret) { ret = BaseRelayRecipient._msgData(); } function supportsInterface(bytes4 interfaceId) public view override(ERC1155Upgradeable, IERC165) returns (bool) { return (interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId)); } }
// SPDX-License-Identifier: MIT // solhint-disable no-inline-assembly pragma solidity >=0.6.9; import "./interfaces/IRelayRecipient.sol"; /** * A base contract to be inherited by any contract that want to receive relayed transactions * A subclass must use "_msgSender()" instead of "msg.sender" */ abstract contract BaseRelayRecipient is IRelayRecipient { /* * Forwarder singleton we accept calls from */ address private _trustedForwarder; function trustedForwarder() public virtual view returns (address){ return _trustedForwarder; } function _setTrustedForwarder(address _forwarder) internal { _trustedForwarder = _forwarder; } function isTrustedForwarder(address forwarder) public virtual override view returns(bool) { return forwarder == _trustedForwarder; } /** * return the sender of this call. * if the call came through our trusted forwarder, return the original sender. * otherwise, return `msg.sender`. * should be used in the contract anywhere instead of msg.sender */ function _msgSender() internal override virtual view returns (address ret) { if (msg.data.length >= 20 && isTrustedForwarder(msg.sender)) { // At this point we know that the sender is a trusted forwarder, // so we trust that the last bytes of msg.data are the verified sender address. // extract sender address from the end of msg.data assembly { ret := shr(96,calldataload(sub(calldatasize(),20))) } } else { ret = msg.sender; } } /** * return the msg.data of this call. * if the call came through our trusted forwarder, then the real sender was appended as the last 20 bytes * of the msg.data - so this method will strip those 20 bytes off. * otherwise (if the call was made directly and not through the forwarder), return `msg.data` * should be used in the contract instead of msg.data, where this difference matters. */ function _msgData() internal override virtual view returns (bytes calldata ret) { if (msg.data.length >= 20 && isTrustedForwarder(msg.sender)) { return msg.data[0:msg.data.length-20]; } else { return msg.data; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.0; import "./IERC1155Upgradeable.sol"; import "./IERC1155ReceiverUpgradeable.sol"; import "./extensions/IERC1155MetadataURIUpgradeable.sol"; import "../../utils/AddressUpgradeable.sol"; import "../../utils/ContextUpgradeable.sol"; import "../../utils/introspection/ERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 * * _Available since v3.1._ */ contract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC1155Upgradeable, IERC1155MetadataURIUpgradeable { using AddressUpgradeable for address; // Mapping from token ID to account balances mapping(uint256 => mapping(address => uint256)) private _balances; // Mapping from account to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ function __ERC1155_init(string memory uri_) internal onlyInitializing { __ERC1155_init_unchained(uri_); } function __ERC1155_init_unchained(string memory uri_) internal onlyInitializing { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) { return interfaceId == type(IERC1155Upgradeable).interfaceId || interfaceId == type(IERC1155MetadataURIUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256) public view virtual override returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { require(account != address(0), "ERC1155: balance query for the zero address"); return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view virtual override returns (uint256[] memory) { require(accounts.length == ids.length, "ERC1155: accounts and ids 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; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual override returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not owner nor approved" ); _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 { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: transfer caller is not owner nor approved" ); _safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, to, ids, amounts, data); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; emit TransferSingle(operator, from, to, id, amount); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); _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 = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; } emit TransferBatch(operator, from, to, ids, amounts); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the amounts in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); _balances[id][to] += amount; emit TransferSingle(operator, address(0), to, id, amount); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); for (uint256 i = 0; i < ids.length; i++) { _balances[ids[i]][to] += amounts[i]; } emit TransferBatch(operator, address(0), to, ids, amounts); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data); } /** * @dev Destroys `amount` tokens of token type `id` from `from` * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `amount` tokens of token type `id`. */ function _burn( address from, uint256 id, uint256 amount ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } emit TransferSingle(operator, from, address(0), id, amount); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Requirements: * * - `ids` and `amounts` must have the same length. */ function _burnBatch( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _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 = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } } emit TransferBatch(operator, from, address(0), ids, amounts); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits a {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC1155: setting approval status for self"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `id` and `amount` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `id` and `amount` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( 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.isContract()) { try IERC1155ReceiverUpgradeable(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { if (response != IERC1155ReceiverUpgradeable.onERC1155Received.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non ERC1155Receiver implementer"); } } } function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { if (to.isContract()) { try IERC1155ReceiverUpgradeable(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( bytes4 response ) { if (response != IERC1155ReceiverUpgradeable.onERC1155BatchReceived.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non ERC1155Receiver implementer"); } } } function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); array[0] = element; return array; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[47] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(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); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/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 paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
pragma solidity ^0.8.4; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; /** * * A custom contract that acts as a CID registry for IPFS directories. * * This contract is a delegate contract used by the [RedditCollectibleAvatars] contract * for its `uri` contruction code. The purpose of it is to determine what IPFS CID * value to use for a given NFT ID. * * The reason why this code exists is to allow the RedditCollectibleAvatars ERC1155 contract * to allow for NFTs to be registered even if the underlying NFT collection expands in size. * This is usually not possible with a ERC1155 contract, unless IPFS isn't used (i.e. you * use your own domain to host the NFT metadata). Because IPFS directories (i.e. where the CID * reflects the contents of a directory) cannot be updated without the CID changing, this router * will handle that CID changing behavior throughout the collection being published. Once the * NFT collection is complete, then the ownership of this contract and the parent * RedditCollectibleAvatars contract will be relinquished so that the NFT collection stays immutable. * * ## How the "routing" works * This contract allows for two things: * 1. Registration of new routes * 2. Resolution of routes via the provided ID * * When the contract is instantiated for the first time, it will require a `itemsPerRoute` value * which specifies how many IPFS metadata files will be stored in each IPFS directory. Then, * when a route is registered (via the `registerRoute()` method), the provided `index` value is * used to reference which IPFS directory the route lives in (and what the `cid` value is). * * With routes registered, when the `lookup()` method is called, it can determine what directory * (or route) the provided `itemIndex` lives in (this happens by diving the `itemIndex` by * the `itemsPerRoute` value). Once determined, the CID value for that `itemIndex` is returned. * * The parent contract (RedditCollectibleAvatars) then uses the CID value and places that into the * IPFS URI that it assembles within the `uri()` method. * * ## What happens if the routes collection expands? * When instantiated, the contract below will pre-fill an array of routes (for performance * reasons) so that it doesn't have to expand the size of the array everytime a new route is * filled. If an when a new route is added that goes beyond the pre-fill size, the registration * code will expand the array by inserting additional cells up until the new route index. * */ error RedditCollectibleAvatarsRouter__UndefinedRouteForItemIndex(uint256 itemIndex, uint totalRoutes, uint256 itemsPerRoute); error RedditCollectibleAvatarsRouter__NotRouteRegisterer(); error RedditCollectibleAvatarsRouter__InvalidArg_AddressZero(); error RedditCollectibleAvatarsRouter__InvalidArg_ItemsPerRouteZero(); contract RedditCollectibleAvatarsRouter is OwnableUpgradeable { event RouteRegistered(uint256 index, string cid); event RouteRegistererUpdated(address current, address previous); event ItemsPerRouteUpdated(uint256 current, uint256 previous); mapping(uint256 => string) public routes; uint256 internal _totalRoutes; uint256 public itemsPerRoute; address public routeRegisterer; /** * @param _itemsPerRoute used to specify how many entries will live in each route (in each IPFS dir) */ function initialize(uint256 _itemsPerRoute, address _routeRegisterer, address owner) public initializer { itemsPerRoute = _itemsPerRoute; routeRegisterer = _routeRegisterer; OwnableUpgradeable.__Ownable_init(); if (owner != _msgSender()) { OwnableUpgradeable.transferOwnership(owner); } } /** * Registers a new route in the contract * * @param index the index of the route (IFPS directory index) * @param cid the IPFS cid value for that route (IPFS directory) */ function registerRoute(uint256 index, string calldata cid) public { if (_msgSender() != routeRegisterer) { revert RedditCollectibleAvatarsRouter__NotRouteRegisterer(); } if (bytes(routes[index]).length == 0){ _totalRoutes += 1; } if (bytes(cid).length == 0){ _totalRoutes -= 1; } routes[index] = cid; emit RouteRegistered(index, cid); } /** * Returns the CID value for the given `itemIndex` by looking up the associated route * * @param itemIndex the index of the item (the NFT token ID) */ function lookup(uint256 itemIndex) public view returns (string memory) { uint256 index = itemIndex / itemsPerRoute; string memory cid = routes[index]; if (bytes(cid).length == 0) { revert RedditCollectibleAvatarsRouter__UndefinedRouteForItemIndex({itemIndex: itemIndex, totalRoutes: _totalRoutes, itemsPerRoute: itemsPerRoute}); } return cid; } /** * Returns how many routes have been registered * * Note that this value is effected by the `initialRoutesCount` value as well. */ function getTotalRoutes() public view returns (uint) { return _totalRoutes; } /** * Sets the `routeRegisterer` wallet address on the contract (note that only the `owner` wallet can execute this action) */ function setRouteRegisterer(address account) public onlyOwner { if (account == address(0)){ revert RedditCollectibleAvatarsRouter__InvalidArg_AddressZero(); } emit RouteRegistererUpdated({current: account, previous: routeRegisterer}); routeRegisterer = account; } /** * Sets `itemsPerRoute` (note that only the `owner` wallet can execute this action) * This function should be used cautiously. This redistributes tokenIDs to potentially different CIDs. */ function setItemsPerRoute(uint256 _itemsPerRoute) public onlyOwner { if (_itemsPerRoute == 0){ revert RedditCollectibleAvatarsRouter__InvalidArg_ItemsPerRouteZero(); } emit ItemsPerRouteUpdated({current: _itemsPerRoute, previous: itemsPerRoute}); itemsPerRoute = _itemsPerRoute; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; /** * a contract must implement this interface in order to support relayed transaction. * It is better to inherit the BaseRelayRecipient as its implementation. */ abstract contract IRelayRecipient { /** * return if the forwarder is trusted to forward relayed transactions to us. * the forwarder is required to verify the sender's signature, and verify * the call is not a replay. */ function isTrustedForwarder(address forwarder) public virtual view returns(bool); /** * return the sender of this call. * if the call came through our trusted forwarder, then the real sender is appended as the last 20 bytes * of the msg.data. * otherwise, return `msg.sender` * should be used in the contract anywhere instead of msg.sender */ function _msgSender() internal virtual view returns (address); /** * return the msg.data of this call. * if the call came through our trusted forwarder, then the real sender was appended as the last 20 bytes * of the msg.data - so this method will strip those 20 bytes off. * otherwise (if the call was made directly and not through the forwarder), return `msg.data` * should be used in the contract instead of msg.data, where this difference matters. */ function _msgData() internal virtual view returns (bytes calldata); function versionRecipient() external virtual view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165Upgradeable.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155Upgradeable is IERC165Upgradeable { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165Upgradeable.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155ReceiverUpgradeable is IERC165Upgradeable { /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.0; import "../IERC1155Upgradeable.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. * * _Available since v3.1._ */ interface IERC1155MetadataURIUpgradeable is IERC1155Upgradeable { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = _setInitializedVersion(1); if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { bool isTopLevelCall = _setInitializedVersion(version); if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(version); } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { _setInitializedVersion(type(uint8).max); } function _setInitializedVersion(uint8 version) private returns (bool) { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level // of initializers, because in other contexts the contract may have been reentered. if (_initializing) { require( version == 1 && !AddressUpgradeable.isContract(address(this)), "Initializable: contract is already initialized" ); return false; } else { require(_initialized < version, "Initializable: contract is already initialized"); _initialized = version; return true; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"RedditCollectibleAvatars__AlreadyMinted","type":"error"},{"inputs":[],"name":"RedditCollectibleAvatars__InvalidArg_AddressZero","type":"error"},{"inputs":[{"internalType":"uint16","name":"basisPoints","type":"uint16"}],"name":"RedditCollectibleAvatars__InvalidArg_SellerFeeBasisPoints","type":"error"},{"inputs":[],"name":"RedditCollectibleAvatars__InvalidArg_TokenAndAddressLengthMismatch","type":"error"},{"inputs":[],"name":"RedditCollectibleAvatars__NotMinter","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"current","type":"string"},{"indexed":false,"internalType":"string","name":"previous","type":"string"}],"name":"ContractURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"current","type":"address"},{"indexed":false,"internalType":"address","name":"prevMinter","type":"address"},{"indexed":false,"internalType":"address","name":"removedMinter","type":"address"}],"name":"MinterUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"removedMinter","type":"address"}],"name":"PreviousMinterCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"current","type":"address"},{"indexed":false,"internalType":"address","name":"previous","type":"address"}],"name":"RouterAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"currentRecipient","type":"address"},{"indexed":false,"internalType":"uint16","name":"currentBasisPoints","type":"uint16"},{"indexed":false,"internalType":"address","name":"previousRecipient","type":"address"},{"indexed":false,"internalType":"uint16","name":"previousBasisPoints","type":"uint16"}],"name":"RoyaltiesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"current","type":"address"},{"indexed":false,"internalType":"address","name":"previous","type":"address"}],"name":"TrustedForwarderUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"_router","outputs":[{"internalType":"contract RedditCollectibleAvatarsRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"address[]","name":"ownerIds","type":"address[]"}],"name":"batchMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clearPreviousMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint16","name":"basisPoints","type":"uint16"}],"internalType":"struct RedditCollectibleAvatars.RoyaltyInfo","name":"_royalties","type":"tuple"},{"internalType":"address","name":"routerAddress","type":"address"},{"internalType":"address","name":"minterAddress","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"forwarder","type":"address"},{"internalType":"string","name":"contracturi","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"ownerId","type":"address"}],"name":"mintNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prevMinter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"royalties","outputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint16","name":"basisPoints","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"setMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"routerAddress","type":"address"}],"name":"setRouterAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"trustedForwarder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"contracturi","type":"string"}],"name":"updateContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint16","name":"basisPoints","type":"uint16"}],"internalType":"struct RedditCollectibleAvatars.RoyaltyInfo","name":"_royalties","type":"tuple"}],"name":"updateRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"updateTrustedForwarder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"versionRecipient","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061525c806100206000396000f3fe608060405234801561001057600080fd5b50600436106101ce5760003560e01c80637d6bd61311610104578063e985e9c5116100a2578063f2fde38b11610071578063f2fde38b14610509578063f31ceecf14610525578063f90b031114610541578063fca3b5aa1461055d576101ce565b8063e985e9c514610480578063edae876f146104b0578063f053dc5c146104ce578063f242432a146104ed576101ce565b80638da5cb5b116100de5780638da5cb5b1461041e578063a22cb4651461043c578063b351026714610458578063e8a3d48514610462576101ce565b80637d6bd613146103c85780637da0a877146103e45780637e5b1e2414610402576101ce565b8063486ff0cd116101715780635a86c41a1161014b5780635a86c41a14610368578063669f5a5114610384578063715018a6146103a0578063747cdccc146103aa576101ce565b8063486ff0cd146102ea5780634e1273f414610308578063572b6c0514610338576101ce565b80630e89341c116101ad5780630e89341c146102515780632a55205a146102815780632eb2c2d6146102b257806341cb87fc146102ce576101ce565b8062fdd58e146101d357806301ffc9a7146102035780630754617214610233575b600080fd5b6101ed60048036038101906101e89190613141565b610579565b6040516101fa9190613190565b60405180910390f35b61021d60048036038101906102189190613203565b610665565b60405161022a919061324b565b60405180910390f35b61023b6106df565b6040516102489190613275565b60405180910390f35b61026b60048036038101906102669190613290565b610705565b6040516102789190613356565b60405180910390f35b61029b60048036038101906102969190613378565b6107ed565b6040516102a99291906133b8565b60405180910390f35b6102cc60048036038101906102c791906135de565b610851565b005b6102e860048036038101906102e391906136ad565b6108f2565b005b6102f261097a565b6040516102ff9190613356565b60405180910390f35b610322600480360381019061031d919061379d565b610a08565b60405161032f91906138d3565b60405180910390f35b610352600480360381019061034d91906136ad565b610b21565b60405161035f919061324b565b60405180910390f35b610382600480360381019061037d91906139a6565b610b7b565b005b61039e60048036038101906103999190613a27565b610d2a565b005b6103a8610e38565b005b6103b2610ec0565b6040516103bf9190613275565b60405180910390f35b6103e260048036038101906103dd9190613ae1565b610ee6565b005b6103ec6110ff565b6040516103f99190613275565b60405180910390f35b61041c60048036038101906104179190613b90565b611129565b005b6104266111f7565b6040516104339190613275565b60405180910390f35b61045660048036038101906104519190613c09565b611221565b005b610460611237565b005b61046a611350565b6040516104779190613356565b60405180910390f35b61049a60048036038101906104959190613c49565b6113e2565b6040516104a7919061324b565b60405180910390f35b6104b8611476565b6040516104c59190613ce8565b60405180910390f35b6104d661149c565b6040516104e4929190613d20565b60405180910390f35b61050760048036038101906105029190613d49565b6114dc565b005b610523600480360381019061051e91906136ad565b61157d565b005b61053f600480360381019061053a9190613de0565b611675565b005b61055b600480360381019061055691906136ad565b6116fd565b005b610577600480360381019061057291906136ad565b611785565b005b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156105ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e190613e7f565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff1660d0600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461065757600061065a565b60015b60ff16905092915050565b60007f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806106d857506106d78261198e565b5b9050919050565b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060600060cd60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630a874df6846040518263ffffffff1660e01b81526004016107649190613190565b60006040518083038186803b15801561077c57600080fd5b505afa158015610790573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906107b99190613f40565b9050806107c584611a70565b6040516020016107d69291906140a9565b604051602081830303815290604052915050919050565b60008060ce60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915061271060ce60000160149054906101000a900461ffff1661ffff168461083e919061411d565b61084891906141a6565b90509250929050565b610859611bd1565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16148061089f575061089e85610899611bd1565b6113e2565b5b6108de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d590614249565b60405180910390fd5b6108eb8585858585611be0565b5050505050565b6108fa611bd1565b73ffffffffffffffffffffffffffffffffffffffff166109186111f7565b73ffffffffffffffffffffffffffffffffffffffff161461096e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610965906142b5565b60405180910390fd5b61097781611e9b565b50565b60ca805461098790614304565b80601f01602080910402602001604051908101604052809291908181526020018280546109b390614304565b8015610a005780601f106109d557610100808354040283529160200191610a00565b820191906000526020600020905b8154815290600101906020018083116109e357829003601f168201915b505050505081565b60608151835114610a4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a45906143a8565b60405180910390fd5b6000835167ffffffffffffffff811115610a6b57610a6a6133e6565b5b604051908082528060200260200182016040528015610a995781602001602082028036833780820191505090505b50905060005b8451811015610b1657610ae6858281518110610abe57610abd6143c8565b5b6020026020010151858381518110610ad957610ad86143c8565b5b6020026020010151610579565b828281518110610af957610af86143c8565b5b60200260200101818152505080610b0f906143f7565b9050610a9f565b508091505092915050565b600060c960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b6000610b85611bd1565b905060cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015610c33575060cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b15610c6a576040517f9a947c6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828290508585905014610ca9576040517f6848ffbe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b85859050811015610d2257610d11848483818110610ccd57610ccc6143c8565b5b9050602002016020810190610ce291906136ad565b878784818110610cf557610cf46143c8565b5b9050602002013560405180602001604052806000815250611fa1565b80610d1b906143f7565b9050610cac565b505050505050565b6000610d34611bd1565b905060cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015610de2575060cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b15610e19576040517f9a947c6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e33828460405180602001604052806000815250611fa1565b505050565b610e40611bd1565b73ffffffffffffffffffffffffffffffffffffffff16610e5e6111f7565b73ffffffffffffffffffffffffffffffffffffffff1614610eb4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eab906142b5565b60405180910390fd5b610ebe60006121a9565b565b60cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610ef2600161226f565b90508015610f16576001600060016101000a81548160ff0219169083151502179055505b610f546040518060400160405280600181526020017f5f0000000000000000000000000000000000000000000000000000000000000081525061235f565b610f5d886123ba565b8560cb60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600060cc60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610fe987611e9b565b610ff2846124d7565b828260cf9190611003929190612f70565b5061100c612523565b611014611bd1565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16146110505761104f8561157d565b5b6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525060ca908051906020019061109b929190612ff6565b5080156110f55760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860016040516110ec9190614488565b60405180910390a15b5050505050505050565b600060c960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611131611bd1565b73ffffffffffffffffffffffffffffffffffffffff1661114f6111f7565b73ffffffffffffffffffffffffffffffffffffffff16146111a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119c906142b5565b60405180910390fd5b7fc9c7c3fe08b88b4df9d4d47ef47d2c43d55c025a0ba88ca442580ed9e7348a16828260cf6040516111d993929190614565565b60405180910390a1818160cf91906111f2929190612f70565b505050565b6000609760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61123361122c611bd1565b838361257c565b5050565b61123f611bd1565b73ffffffffffffffffffffffffffffffffffffffff1661125d6111f7565b73ffffffffffffffffffffffffffffffffffffffff16146112b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112aa906142b5565b60405180910390fd5b7f268bf6c7563609628a434e87b68c51533fd6e4991976ed6eb9fdd5357e51a0b260cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516113049190613275565b60405180910390a1600060cc60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b606060cf805461135f90614304565b80601f016020809104026020016040519081016040528092919081815260200182805461138b90614304565b80156113d85780601f106113ad576101008083540402835291602001916113d8565b820191906000526020600020905b8154815290600101906020018083116113bb57829003601f168201915b5050505050905090565b6000606660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60cd60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60ce8060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900461ffff16905082565b6114e4611bd1565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16148061152a575061152985611524611bd1565b6113e2565b5b611569576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156090614610565b60405180910390fd5b61157685858585856126e9565b5050505050565b611585611bd1565b73ffffffffffffffffffffffffffffffffffffffff166115a36111f7565b73ffffffffffffffffffffffffffffffffffffffff16146115f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115f0906142b5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611669576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611660906146a2565b60405180910390fd5b611672816121a9565b50565b61167d611bd1565b73ffffffffffffffffffffffffffffffffffffffff1661169b6111f7565b73ffffffffffffffffffffffffffffffffffffffff16146116f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116e8906142b5565b60405180910390fd5b6116fa816123ba565b50565b611705611bd1565b73ffffffffffffffffffffffffffffffffffffffff166117236111f7565b73ffffffffffffffffffffffffffffffffffffffff1614611779576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611770906142b5565b60405180910390fd5b611782816124d7565b50565b61178d611bd1565b73ffffffffffffffffffffffffffffffffffffffff166117ab6111f7565b73ffffffffffffffffffffffffffffffffffffffff1614611801576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117f8906142b5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611868576040517fe139a5b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f295216bda8b30e71fdcbf4634a63f1de743bc26c49280895bde1341094d39eae8160cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516118df939291906146c2565b60405180910390a160cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660cc60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060cb60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60007fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611a5957507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611a695750611a688261293a565b5b9050919050565b60606000821415611ab8576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050611bcc565b600082905060005b60008214611aea578080611ad3906143f7565b915050600a82611ae391906141a6565b9150611ac0565b60008167ffffffffffffffff811115611b0657611b056133e6565b5b6040519080825280601f01601f191660200182016040528015611b385781602001600182028036833780820191505090505b5090505b60008514611bc557600182611b5191906146f9565b9150600a85611b60919061472d565b6030611b6c919061475e565b60f81b818381518110611b8257611b816143c8565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85611bbe91906141a6565b9450611b3c565b8093505050505b919050565b6000611bdb6129a4565b905090565b8151835114611c24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1b90614826565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415611c94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8b906148b8565b60405180910390fd5b6000611c9e611bd1565b905060005b8451811015611e06576000858281518110611cc157611cc06143c8565b5b602002602001015190506000858381518110611ce057611cdf6143c8565b5b602002602001015190508873ffffffffffffffffffffffffffffffffffffffff1660d0600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015611d585750600281105b611d97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d8e9061494a565b60405180910390fd5b6001811415611df3578760d0600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b505080611dff906143f7565b9050611ca3565b508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051611e7d92919061496a565b60405180910390a4611e938187878787876129db565b505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611f02576040517fe139a5b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f1b40f7040327d783cc3cffdd488e8233012f50d648b53c5218f73ef4a5b714058160cd60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051611f559291906149a1565b60405180910390a18060cd60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612011576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161200890614a3c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660d0600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146120b557816040517fe43239130000000000000000000000000000000000000000000000000000000081526004016120ac9190613190565b60405180910390fd5b60006120bf611bd1565b90508360d0600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6286600160405161218b929190614a8d565b60405180910390a46121a38160008686600187612bc2565b50505050565b6000609760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081609760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008060019054906101000a900460ff16156122e65760018260ff1614801561229e575061229c30612da9565b155b6122dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122d490614b28565b60405180910390fd5b6000905061235a565b8160ff1660008054906101000a900460ff1660ff161061233b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161233290614b28565b60405180910390fd5b816000806101000a81548160ff021916908360ff160217905550600190505b919050565b600060019054906101000a900460ff166123ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123a590614bba565b60405180910390fd5b6123b781612dcc565b50565b6127108160200160208101906123d09190614c06565b61ffff161115612429578060200160208101906123ed9190614c06565b6040517f816e05420000000000000000000000000000000000000000000000000000000081526004016124209190614c33565b60405180910390fd5b7f92aef7ecf41cb555da3bf0e55f1ec5a9632efafc327453353e10b4b569ce9cef81600001602081019061245d91906136ad565b8260200160208101906124709190614c06565b60ce60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660ce60000160149054906101000a900461ffff166040516124ba9493929190614c4e565b60405180910390a18060ce81816124d19190614e1b565b90505050565b7f06710129fbc2650f48c82631edcea255e102cd5e17c444deb7273855cfb5e77d816125016110ff565b60405161250f9291906149a1565b60405180910390a161252081612e27565b50565b600060019054906101000a900460ff16612572576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161256990614bba565b60405180910390fd5b61257a612e6b565b565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156125eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125e290614e9b565b60405180910390fd5b80606660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516126dc919061324b565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415612759576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612750906148b8565b60405180910390fd5b6000612763611bd1565b9050600061277085612ecc565b9050600061277d85612ecc565b905061278d838989858589612f46565b8773ffffffffffffffffffffffffffffffffffffffff1660d0600088815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161480156127fb5750600285105b61283a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128319061494a565b60405180910390fd5b6001851415612896578660d0600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b8673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62898960405161290c929190614ebb565b60405180910390a4612922838989858589612f4e565b612930838989898989612bc2565b5050505050505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600060146000369050101580156129c057506129bf33610b21565b5b156129d457601436033560601c90506129d8565b3390505b90565b6129fa8473ffffffffffffffffffffffffffffffffffffffff16612da9565b15612bba578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b8152600401612a40959493929190614f39565b602060405180830381600087803b158015612a5a57600080fd5b505af1925050508015612a8b57506040513d601f19601f82011682018060405250810190612a889190614fb6565b60015b612b3157612a97614ff0565b806308c379a01415612af45750612aac615012565b80612ab75750612af6565b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aeb9190613356565b60405180910390fd5b505b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b289061511a565b60405180910390fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612bb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612baf906151ac565b60405180910390fd5b505b505050505050565b612be18473ffffffffffffffffffffffffffffffffffffffff16612da9565b15612da1578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401612c279594939291906151cc565b602060405180830381600087803b158015612c4157600080fd5b505af1925050508015612c7257506040513d601f19601f82011682018060405250810190612c6f9190614fb6565b60015b612d1857612c7e614ff0565b806308c379a01415612cdb5750612c93615012565b80612c9e5750612cdd565b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cd29190613356565b60405180910390fd5b505b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d0f9061511a565b60405180910390fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612d9f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d96906151ac565b60405180910390fd5b505b505050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600060019054906101000a900460ff16612e1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e1290614bba565b60405180910390fd5b612e2481612f56565b50565b8060c960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600060019054906101000a900460ff16612eba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eb190614bba565b60405180910390fd5b612eca612ec5611bd1565b6121a9565b565b60606000600167ffffffffffffffff811115612eeb57612eea6133e6565b5b604051908082528060200260200182016040528015612f195781602001602082028036833780820191505090505b5090508281600081518110612f3157612f306143c8565b5b60200260200101818152505080915050919050565b505050505050565b505050505050565b8060679080519060200190612f6c929190612ff6565b5050565b828054612f7c90614304565b90600052602060002090601f016020900481019282612f9e5760008555612fe5565b82601f10612fb757803560ff1916838001178555612fe5565b82800160010185558215612fe5579182015b82811115612fe4578235825591602001919060010190612fc9565b5b509050612ff2919061307c565b5090565b82805461300290614304565b90600052602060002090601f016020900481019282613024576000855561306b565b82601f1061303d57805160ff191683800117855561306b565b8280016001018555821561306b579182015b8281111561306a57825182559160200191906001019061304f565b5b509050613078919061307c565b5090565b5b8082111561309557600081600090555060010161307d565b5090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006130d8826130ad565b9050919050565b6130e8816130cd565b81146130f357600080fd5b50565b600081359050613105816130df565b92915050565b6000819050919050565b61311e8161310b565b811461312957600080fd5b50565b60008135905061313b81613115565b92915050565b60008060408385031215613158576131576130a3565b5b6000613166858286016130f6565b92505060206131778582860161312c565b9150509250929050565b61318a8161310b565b82525050565b60006020820190506131a56000830184613181565b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6131e0816131ab565b81146131eb57600080fd5b50565b6000813590506131fd816131d7565b92915050565b600060208284031215613219576132186130a3565b5b6000613227848285016131ee565b91505092915050565b60008115159050919050565b61324581613230565b82525050565b6000602082019050613260600083018461323c565b92915050565b61326f816130cd565b82525050565b600060208201905061328a6000830184613266565b92915050565b6000602082840312156132a6576132a56130a3565b5b60006132b48482850161312c565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156132f75780820151818401526020810190506132dc565b83811115613306576000848401525b50505050565b6000601f19601f8301169050919050565b6000613328826132bd565b61333281856132c8565b93506133428185602086016132d9565b61334b8161330c565b840191505092915050565b60006020820190508181036000830152613370818461331d565b905092915050565b6000806040838503121561338f5761338e6130a3565b5b600061339d8582860161312c565b92505060206133ae8582860161312c565b9150509250929050565b60006040820190506133cd6000830185613266565b6133da6020830184613181565b9392505050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61341e8261330c565b810181811067ffffffffffffffff8211171561343d5761343c6133e6565b5b80604052505050565b6000613450613099565b905061345c8282613415565b919050565b600067ffffffffffffffff82111561347c5761347b6133e6565b5b602082029050602081019050919050565b600080fd5b60006134a56134a084613461565b613446565b905080838252602082019050602084028301858111156134c8576134c761348d565b5b835b818110156134f157806134dd888261312c565b8452602084019350506020810190506134ca565b5050509392505050565b600082601f8301126135105761350f6133e1565b5b8135613520848260208601613492565b91505092915050565b600080fd5b600067ffffffffffffffff821115613549576135486133e6565b5b6135528261330c565b9050602081019050919050565b82818337600083830152505050565b600061358161357c8461352e565b613446565b90508281526020810184848401111561359d5761359c613529565b5b6135a884828561355f565b509392505050565b600082601f8301126135c5576135c46133e1565b5b81356135d584826020860161356e565b91505092915050565b600080600080600060a086880312156135fa576135f96130a3565b5b6000613608888289016130f6565b9550506020613619888289016130f6565b945050604086013567ffffffffffffffff81111561363a576136396130a8565b5b613646888289016134fb565b935050606086013567ffffffffffffffff811115613667576136666130a8565b5b613673888289016134fb565b925050608086013567ffffffffffffffff811115613694576136936130a8565b5b6136a0888289016135b0565b9150509295509295909350565b6000602082840312156136c3576136c26130a3565b5b60006136d1848285016130f6565b91505092915050565b600067ffffffffffffffff8211156136f5576136f46133e6565b5b602082029050602081019050919050565b6000613719613714846136da565b613446565b9050808382526020820190506020840283018581111561373c5761373b61348d565b5b835b81811015613765578061375188826130f6565b84526020840193505060208101905061373e565b5050509392505050565b600082601f830112613784576137836133e1565b5b8135613794848260208601613706565b91505092915050565b600080604083850312156137b4576137b36130a3565b5b600083013567ffffffffffffffff8111156137d2576137d16130a8565b5b6137de8582860161376f565b925050602083013567ffffffffffffffff8111156137ff576137fe6130a8565b5b61380b858286016134fb565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61384a8161310b565b82525050565b600061385c8383613841565b60208301905092915050565b6000602082019050919050565b600061388082613815565b61388a8185613820565b935061389583613831565b8060005b838110156138c65781516138ad8882613850565b97506138b883613868565b925050600181019050613899565b5085935050505092915050565b600060208201905081810360008301526138ed8184613875565b905092915050565b600080fd5b60008083601f8401126139105761390f6133e1565b5b8235905067ffffffffffffffff81111561392d5761392c6138f5565b5b6020830191508360208202830111156139495761394861348d565b5b9250929050565b60008083601f840112613966576139656133e1565b5b8235905067ffffffffffffffff811115613983576139826138f5565b5b60208301915083602082028301111561399f5761399e61348d565b5b9250929050565b600080600080604085870312156139c0576139bf6130a3565b5b600085013567ffffffffffffffff8111156139de576139dd6130a8565b5b6139ea878288016138fa565b9450945050602085013567ffffffffffffffff811115613a0d57613a0c6130a8565b5b613a1987828801613950565b925092505092959194509250565b60008060408385031215613a3e57613a3d6130a3565b5b6000613a4c8582860161312c565b9250506020613a5d858286016130f6565b9150509250929050565b600080fd5b600060408284031215613a8257613a81613a67565b5b81905092915050565b60008083601f840112613aa157613aa06133e1565b5b8235905067ffffffffffffffff811115613abe57613abd6138f5565b5b602083019150836001820283011115613ada57613ad961348d565b5b9250929050565b600080600080600080600060e0888a031215613b0057613aff6130a3565b5b6000613b0e8a828b01613a6c565b9750506040613b1f8a828b016130f6565b9650506060613b308a828b016130f6565b9550506080613b418a828b016130f6565b94505060a0613b528a828b016130f6565b93505060c088013567ffffffffffffffff811115613b7357613b726130a8565b5b613b7f8a828b01613a8b565b925092505092959891949750929550565b60008060208385031215613ba757613ba66130a3565b5b600083013567ffffffffffffffff811115613bc557613bc46130a8565b5b613bd185828601613a8b565b92509250509250929050565b613be681613230565b8114613bf157600080fd5b50565b600081359050613c0381613bdd565b92915050565b60008060408385031215613c2057613c1f6130a3565b5b6000613c2e858286016130f6565b9250506020613c3f85828601613bf4565b9150509250929050565b60008060408385031215613c6057613c5f6130a3565b5b6000613c6e858286016130f6565b9250506020613c7f858286016130f6565b9150509250929050565b6000819050919050565b6000613cae613ca9613ca4846130ad565b613c89565b6130ad565b9050919050565b6000613cc082613c93565b9050919050565b6000613cd282613cb5565b9050919050565b613ce281613cc7565b82525050565b6000602082019050613cfd6000830184613cd9565b92915050565b600061ffff82169050919050565b613d1a81613d03565b82525050565b6000604082019050613d356000830185613266565b613d426020830184613d11565b9392505050565b600080600080600060a08688031215613d6557613d646130a3565b5b6000613d73888289016130f6565b9550506020613d84888289016130f6565b9450506040613d958882890161312c565b9350506060613da68882890161312c565b925050608086013567ffffffffffffffff811115613dc757613dc66130a8565b5b613dd3888289016135b0565b9150509295509295909350565b600060408284031215613df657613df56130a3565b5b6000613e0484828501613a6c565b91505092915050565b7f455243313135353a2062616c616e636520717565727920666f7220746865207a60008201527f65726f2061646472657373000000000000000000000000000000000000000000602082015250565b6000613e69602b836132c8565b9150613e7482613e0d565b604082019050919050565b60006020820190508181036000830152613e9881613e5c565b9050919050565b600067ffffffffffffffff821115613eba57613eb96133e6565b5b613ec38261330c565b9050602081019050919050565b6000613ee3613ede84613e9f565b613446565b905082815260208101848484011115613eff57613efe613529565b5b613f0a8482856132d9565b509392505050565b600082601f830112613f2757613f266133e1565b5b8151613f37848260208601613ed0565b91505092915050565b600060208284031215613f5657613f556130a3565b5b600082015167ffffffffffffffff811115613f7457613f736130a8565b5b613f8084828501613f12565b91505092915050565b600081905092915050565b7f697066733a2f2f00000000000000000000000000000000000000000000000000600082015250565b6000613fca600783613f89565b9150613fd582613f94565b600782019050919050565b6000613feb826132bd565b613ff58185613f89565b93506140058185602086016132d9565b80840191505092915050565b7f2f00000000000000000000000000000000000000000000000000000000000000600082015250565b6000614047600183613f89565b915061405282614011565b600182019050919050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000600082015250565b6000614093600583613f89565b915061409e8261405d565b600582019050919050565b60006140b482613fbd565b91506140c08285613fe0565b91506140cb8261403a565b91506140d78284613fe0565b91506140e282614086565b91508190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006141288261310b565b91506141338361310b565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561416c5761416b6140ee565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006141b18261310b565b91506141bc8361310b565b9250826141cc576141cb614177565b5b828204905092915050565b7f455243313135353a207472616e736665722063616c6c6572206973206e6f742060008201527f6f776e6572206e6f7220617070726f7665640000000000000000000000000000602082015250565b60006142336032836132c8565b915061423e826141d7565b604082019050919050565b6000602082019050818103600083015261426281614226565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061429f6020836132c8565b91506142aa82614269565b602082019050919050565b600060208201905081810360008301526142ce81614292565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061431c57607f821691505b602082108114156143305761432f6142d5565b5b50919050565b7f455243313135353a206163636f756e747320616e6420696473206c656e67746860008201527f206d69736d617463680000000000000000000000000000000000000000000000602082015250565b60006143926029836132c8565b915061439d82614336565b604082019050919050565b600060208201905081810360008301526143c181614385565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006144028261310b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415614435576144346140ee565b5b600182019050919050565b6000819050919050565b600060ff82169050919050565b600061447261446d61446884614440565b613c89565b61444a565b9050919050565b61448281614457565b82525050565b600060208201905061449d6000830184614479565b92915050565b60006144af83856132c8565b93506144bc83858461355f565b6144c58361330c565b840190509392505050565b60008190508160005260206000209050919050565b600081546144f281614304565b6144fc81866132c8565b9450600182166000811461451757600181146145295761455c565b60ff198316865260208601935061455c565b614532856144d0565b60005b8381101561455457815481890152600182019150602081019050614535565b808801955050505b50505092915050565b600060408201905081810360008301526145808185876144a3565b9050818103602083015261459481846144e5565b9050949350505050565b7f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260008201527f20617070726f7665640000000000000000000000000000000000000000000000602082015250565b60006145fa6029836132c8565b91506146058261459e565b604082019050919050565b60006020820190508181036000830152614629816145ed565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061468c6026836132c8565b915061469782614630565b604082019050919050565b600060208201905081810360008301526146bb8161467f565b9050919050565b60006060820190506146d76000830186613266565b6146e46020830185613266565b6146f16040830184613266565b949350505050565b60006147048261310b565b915061470f8361310b565b925082821015614722576147216140ee565b5b828203905092915050565b60006147388261310b565b91506147438361310b565b92508261475357614752614177565b5b828206905092915050565b60006147698261310b565b91506147748361310b565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156147a9576147a86140ee565b5b828201905092915050565b7f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060008201527f6d69736d61746368000000000000000000000000000000000000000000000000602082015250565b60006148106028836132c8565b915061481b826147b4565b604082019050919050565b6000602082019050818103600083015261483f81614803565b9050919050565b7f455243313135353a207472616e7366657220746f20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b60006148a26025836132c8565b91506148ad82614846565b604082019050919050565b600060208201905081810360008301526148d181614895565b9050919050565b7f455243313135353a20696e73756666696369656e742062616c616e636520666f60008201527f72207472616e7366657200000000000000000000000000000000000000000000602082015250565b6000614934602a836132c8565b915061493f826148d8565b604082019050919050565b6000602082019050818103600083015261496381614927565b9050919050565b600060408201905081810360008301526149848185613875565b905081810360208301526149988184613875565b90509392505050565b60006040820190506149b66000830185613266565b6149c36020830184613266565b9392505050565b7f455243313135353a206d696e7420746f20746865207a65726f2061646472657360008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b6000614a266021836132c8565b9150614a31826149ca565b604082019050919050565b60006020820190508181036000830152614a5581614a19565b9050919050565b6000614a77614a72614a6d84614440565b613c89565b61310b565b9050919050565b614a8781614a5c565b82525050565b6000604082019050614aa26000830185613181565b614aaf6020830184614a7e565b9392505050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b6000614b12602e836132c8565b9150614b1d82614ab6565b604082019050919050565b60006020820190508181036000830152614b4181614b05565b9050919050565b7f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960008201527f6e697469616c697a696e67000000000000000000000000000000000000000000602082015250565b6000614ba4602b836132c8565b9150614baf82614b48565b604082019050919050565b60006020820190508181036000830152614bd381614b97565b9050919050565b614be381613d03565b8114614bee57600080fd5b50565b600081359050614c0081614bda565b92915050565b600060208284031215614c1c57614c1b6130a3565b5b6000614c2a84828501614bf1565b91505092915050565b6000602082019050614c486000830184613d11565b92915050565b6000608082019050614c636000830187613266565b614c706020830186613d11565b614c7d6040830185613266565b614c8a6060830184613d11565b95945050505050565b60008135614ca0816130df565b80915050919050565b60008160001b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff614cd684614ca9565b9350801983169250808416831791505092915050565b6000614cf782613cb5565b9050919050565b6000819050919050565b614d1182614cec565b614d24614d1d82614cfe565b8354614cb6565b8255505050565b60008135614d3881614bda565b80915050919050565b60008160a01b9050919050565b600075ffff0000000000000000000000000000000000000000614d7084614d41565b9350801983169250808416831791505092915050565b6000614da1614d9c614d9784613d03565b613c89565b613d03565b9050919050565b6000819050919050565b614dbb82614d86565b614dce614dc782614da8565b8354614d4e565b8255505050565b600081016000830180614de781614c93565b9050614df38184614d08565b505050600081016020830180614e0881614d2b565b9050614e148184614db2565b5050505050565b614e258282614dd5565b5050565b7f455243313135353a2073657474696e6720617070726f76616c2073746174757360008201527f20666f722073656c660000000000000000000000000000000000000000000000602082015250565b6000614e856029836132c8565b9150614e9082614e29565b604082019050919050565b60006020820190508181036000830152614eb481614e78565b9050919050565b6000604082019050614ed06000830185613181565b614edd6020830184613181565b9392505050565b600081519050919050565b600082825260208201905092915050565b6000614f0b82614ee4565b614f158185614eef565b9350614f258185602086016132d9565b614f2e8161330c565b840191505092915050565b600060a082019050614f4e6000830188613266565b614f5b6020830187613266565b8181036040830152614f6d8186613875565b90508181036060830152614f818185613875565b90508181036080830152614f958184614f00565b90509695505050505050565b600081519050614fb0816131d7565b92915050565b600060208284031215614fcc57614fcb6130a3565b5b6000614fda84828501614fa1565b91505092915050565b60008160e01c9050919050565b600060033d111561500f5760046000803e61500c600051614fe3565b90505b90565b600060443d1015615022576150a5565b61502a613099565b60043d036004823e80513d602482011167ffffffffffffffff821117156150525750506150a5565b808201805167ffffffffffffffff81111561507057505050506150a5565b80602083010160043d03850181111561508d5750505050506150a5565b61509c82602001850186613415565b82955050505050505b90565b7f455243313135353a207472616e7366657220746f206e6f6e204552433131353560008201527f526563656976657220696d706c656d656e746572000000000000000000000000602082015250565b60006151046034836132c8565b915061510f826150a8565b604082019050919050565b60006020820190508181036000830152615133816150f7565b9050919050565b7f455243313135353a204552433131353552656365697665722072656a6563746560008201527f6420746f6b656e73000000000000000000000000000000000000000000000000602082015250565b60006151966028836132c8565b91506151a18261513a565b604082019050919050565b600060208201905081810360008301526151c581615189565b9050919050565b600060a0820190506151e16000830188613266565b6151ee6020830187613266565b6151fb6040830186613181565b6152086060830185613181565b818103608083015261521a8184614f00565b9050969550505050505056fea26469706673582212206c7042a23df7cccb75e06ba03378ce9dfda478e5fe86bb5ca84873e97d9afe1764736f6c63430008090033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101ce5760003560e01c80637d6bd61311610104578063e985e9c5116100a2578063f2fde38b11610071578063f2fde38b14610509578063f31ceecf14610525578063f90b031114610541578063fca3b5aa1461055d576101ce565b8063e985e9c514610480578063edae876f146104b0578063f053dc5c146104ce578063f242432a146104ed576101ce565b80638da5cb5b116100de5780638da5cb5b1461041e578063a22cb4651461043c578063b351026714610458578063e8a3d48514610462576101ce565b80637d6bd613146103c85780637da0a877146103e45780637e5b1e2414610402576101ce565b8063486ff0cd116101715780635a86c41a1161014b5780635a86c41a14610368578063669f5a5114610384578063715018a6146103a0578063747cdccc146103aa576101ce565b8063486ff0cd146102ea5780634e1273f414610308578063572b6c0514610338576101ce565b80630e89341c116101ad5780630e89341c146102515780632a55205a146102815780632eb2c2d6146102b257806341cb87fc146102ce576101ce565b8062fdd58e146101d357806301ffc9a7146102035780630754617214610233575b600080fd5b6101ed60048036038101906101e89190613141565b610579565b6040516101fa9190613190565b60405180910390f35b61021d60048036038101906102189190613203565b610665565b60405161022a919061324b565b60405180910390f35b61023b6106df565b6040516102489190613275565b60405180910390f35b61026b60048036038101906102669190613290565b610705565b6040516102789190613356565b60405180910390f35b61029b60048036038101906102969190613378565b6107ed565b6040516102a99291906133b8565b60405180910390f35b6102cc60048036038101906102c791906135de565b610851565b005b6102e860048036038101906102e391906136ad565b6108f2565b005b6102f261097a565b6040516102ff9190613356565b60405180910390f35b610322600480360381019061031d919061379d565b610a08565b60405161032f91906138d3565b60405180910390f35b610352600480360381019061034d91906136ad565b610b21565b60405161035f919061324b565b60405180910390f35b610382600480360381019061037d91906139a6565b610b7b565b005b61039e60048036038101906103999190613a27565b610d2a565b005b6103a8610e38565b005b6103b2610ec0565b6040516103bf9190613275565b60405180910390f35b6103e260048036038101906103dd9190613ae1565b610ee6565b005b6103ec6110ff565b6040516103f99190613275565b60405180910390f35b61041c60048036038101906104179190613b90565b611129565b005b6104266111f7565b6040516104339190613275565b60405180910390f35b61045660048036038101906104519190613c09565b611221565b005b610460611237565b005b61046a611350565b6040516104779190613356565b60405180910390f35b61049a60048036038101906104959190613c49565b6113e2565b6040516104a7919061324b565b60405180910390f35b6104b8611476565b6040516104c59190613ce8565b60405180910390f35b6104d661149c565b6040516104e4929190613d20565b60405180910390f35b61050760048036038101906105029190613d49565b6114dc565b005b610523600480360381019061051e91906136ad565b61157d565b005b61053f600480360381019061053a9190613de0565b611675565b005b61055b600480360381019061055691906136ad565b6116fd565b005b610577600480360381019061057291906136ad565b611785565b005b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156105ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e190613e7f565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff1660d0600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461065757600061065a565b60015b60ff16905092915050565b60007f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806106d857506106d78261198e565b5b9050919050565b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060600060cd60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630a874df6846040518263ffffffff1660e01b81526004016107649190613190565b60006040518083038186803b15801561077c57600080fd5b505afa158015610790573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906107b99190613f40565b9050806107c584611a70565b6040516020016107d69291906140a9565b604051602081830303815290604052915050919050565b60008060ce60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915061271060ce60000160149054906101000a900461ffff1661ffff168461083e919061411d565b61084891906141a6565b90509250929050565b610859611bd1565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16148061089f575061089e85610899611bd1565b6113e2565b5b6108de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d590614249565b60405180910390fd5b6108eb8585858585611be0565b5050505050565b6108fa611bd1565b73ffffffffffffffffffffffffffffffffffffffff166109186111f7565b73ffffffffffffffffffffffffffffffffffffffff161461096e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610965906142b5565b60405180910390fd5b61097781611e9b565b50565b60ca805461098790614304565b80601f01602080910402602001604051908101604052809291908181526020018280546109b390614304565b8015610a005780601f106109d557610100808354040283529160200191610a00565b820191906000526020600020905b8154815290600101906020018083116109e357829003601f168201915b505050505081565b60608151835114610a4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a45906143a8565b60405180910390fd5b6000835167ffffffffffffffff811115610a6b57610a6a6133e6565b5b604051908082528060200260200182016040528015610a995781602001602082028036833780820191505090505b50905060005b8451811015610b1657610ae6858281518110610abe57610abd6143c8565b5b6020026020010151858381518110610ad957610ad86143c8565b5b6020026020010151610579565b828281518110610af957610af86143c8565b5b60200260200101818152505080610b0f906143f7565b9050610a9f565b508091505092915050565b600060c960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b6000610b85611bd1565b905060cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015610c33575060cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b15610c6a576040517f9a947c6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828290508585905014610ca9576040517f6848ffbe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b85859050811015610d2257610d11848483818110610ccd57610ccc6143c8565b5b9050602002016020810190610ce291906136ad565b878784818110610cf557610cf46143c8565b5b9050602002013560405180602001604052806000815250611fa1565b80610d1b906143f7565b9050610cac565b505050505050565b6000610d34611bd1565b905060cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015610de2575060cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b15610e19576040517f9a947c6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e33828460405180602001604052806000815250611fa1565b505050565b610e40611bd1565b73ffffffffffffffffffffffffffffffffffffffff16610e5e6111f7565b73ffffffffffffffffffffffffffffffffffffffff1614610eb4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eab906142b5565b60405180910390fd5b610ebe60006121a9565b565b60cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610ef2600161226f565b90508015610f16576001600060016101000a81548160ff0219169083151502179055505b610f546040518060400160405280600181526020017f5f0000000000000000000000000000000000000000000000000000000000000081525061235f565b610f5d886123ba565b8560cb60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600060cc60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610fe987611e9b565b610ff2846124d7565b828260cf9190611003929190612f70565b5061100c612523565b611014611bd1565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16146110505761104f8561157d565b5b6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525060ca908051906020019061109b929190612ff6565b5080156110f55760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860016040516110ec9190614488565b60405180910390a15b5050505050505050565b600060c960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611131611bd1565b73ffffffffffffffffffffffffffffffffffffffff1661114f6111f7565b73ffffffffffffffffffffffffffffffffffffffff16146111a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119c906142b5565b60405180910390fd5b7fc9c7c3fe08b88b4df9d4d47ef47d2c43d55c025a0ba88ca442580ed9e7348a16828260cf6040516111d993929190614565565b60405180910390a1818160cf91906111f2929190612f70565b505050565b6000609760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61123361122c611bd1565b838361257c565b5050565b61123f611bd1565b73ffffffffffffffffffffffffffffffffffffffff1661125d6111f7565b73ffffffffffffffffffffffffffffffffffffffff16146112b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112aa906142b5565b60405180910390fd5b7f268bf6c7563609628a434e87b68c51533fd6e4991976ed6eb9fdd5357e51a0b260cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516113049190613275565b60405180910390a1600060cc60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b606060cf805461135f90614304565b80601f016020809104026020016040519081016040528092919081815260200182805461138b90614304565b80156113d85780601f106113ad576101008083540402835291602001916113d8565b820191906000526020600020905b8154815290600101906020018083116113bb57829003601f168201915b5050505050905090565b6000606660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60cd60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60ce8060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900461ffff16905082565b6114e4611bd1565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16148061152a575061152985611524611bd1565b6113e2565b5b611569576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156090614610565b60405180910390fd5b61157685858585856126e9565b5050505050565b611585611bd1565b73ffffffffffffffffffffffffffffffffffffffff166115a36111f7565b73ffffffffffffffffffffffffffffffffffffffff16146115f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115f0906142b5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611669576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611660906146a2565b60405180910390fd5b611672816121a9565b50565b61167d611bd1565b73ffffffffffffffffffffffffffffffffffffffff1661169b6111f7565b73ffffffffffffffffffffffffffffffffffffffff16146116f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116e8906142b5565b60405180910390fd5b6116fa816123ba565b50565b611705611bd1565b73ffffffffffffffffffffffffffffffffffffffff166117236111f7565b73ffffffffffffffffffffffffffffffffffffffff1614611779576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611770906142b5565b60405180910390fd5b611782816124d7565b50565b61178d611bd1565b73ffffffffffffffffffffffffffffffffffffffff166117ab6111f7565b73ffffffffffffffffffffffffffffffffffffffff1614611801576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117f8906142b5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611868576040517fe139a5b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f295216bda8b30e71fdcbf4634a63f1de743bc26c49280895bde1341094d39eae8160cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516118df939291906146c2565b60405180910390a160cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660cc60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060cb60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60007fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611a5957507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611a695750611a688261293a565b5b9050919050565b60606000821415611ab8576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050611bcc565b600082905060005b60008214611aea578080611ad3906143f7565b915050600a82611ae391906141a6565b9150611ac0565b60008167ffffffffffffffff811115611b0657611b056133e6565b5b6040519080825280601f01601f191660200182016040528015611b385781602001600182028036833780820191505090505b5090505b60008514611bc557600182611b5191906146f9565b9150600a85611b60919061472d565b6030611b6c919061475e565b60f81b818381518110611b8257611b816143c8565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85611bbe91906141a6565b9450611b3c565b8093505050505b919050565b6000611bdb6129a4565b905090565b8151835114611c24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1b90614826565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415611c94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8b906148b8565b60405180910390fd5b6000611c9e611bd1565b905060005b8451811015611e06576000858281518110611cc157611cc06143c8565b5b602002602001015190506000858381518110611ce057611cdf6143c8565b5b602002602001015190508873ffffffffffffffffffffffffffffffffffffffff1660d0600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015611d585750600281105b611d97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d8e9061494a565b60405180910390fd5b6001811415611df3578760d0600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b505080611dff906143f7565b9050611ca3565b508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051611e7d92919061496a565b60405180910390a4611e938187878787876129db565b505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611f02576040517fe139a5b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f1b40f7040327d783cc3cffdd488e8233012f50d648b53c5218f73ef4a5b714058160cd60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051611f559291906149a1565b60405180910390a18060cd60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612011576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161200890614a3c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660d0600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146120b557816040517fe43239130000000000000000000000000000000000000000000000000000000081526004016120ac9190613190565b60405180910390fd5b60006120bf611bd1565b90508360d0600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6286600160405161218b929190614a8d565b60405180910390a46121a38160008686600187612bc2565b50505050565b6000609760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081609760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008060019054906101000a900460ff16156122e65760018260ff1614801561229e575061229c30612da9565b155b6122dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122d490614b28565b60405180910390fd5b6000905061235a565b8160ff1660008054906101000a900460ff1660ff161061233b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161233290614b28565b60405180910390fd5b816000806101000a81548160ff021916908360ff160217905550600190505b919050565b600060019054906101000a900460ff166123ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123a590614bba565b60405180910390fd5b6123b781612dcc565b50565b6127108160200160208101906123d09190614c06565b61ffff161115612429578060200160208101906123ed9190614c06565b6040517f816e05420000000000000000000000000000000000000000000000000000000081526004016124209190614c33565b60405180910390fd5b7f92aef7ecf41cb555da3bf0e55f1ec5a9632efafc327453353e10b4b569ce9cef81600001602081019061245d91906136ad565b8260200160208101906124709190614c06565b60ce60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660ce60000160149054906101000a900461ffff166040516124ba9493929190614c4e565b60405180910390a18060ce81816124d19190614e1b565b90505050565b7f06710129fbc2650f48c82631edcea255e102cd5e17c444deb7273855cfb5e77d816125016110ff565b60405161250f9291906149a1565b60405180910390a161252081612e27565b50565b600060019054906101000a900460ff16612572576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161256990614bba565b60405180910390fd5b61257a612e6b565b565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156125eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125e290614e9b565b60405180910390fd5b80606660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516126dc919061324b565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415612759576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612750906148b8565b60405180910390fd5b6000612763611bd1565b9050600061277085612ecc565b9050600061277d85612ecc565b905061278d838989858589612f46565b8773ffffffffffffffffffffffffffffffffffffffff1660d0600088815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161480156127fb5750600285105b61283a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128319061494a565b60405180910390fd5b6001851415612896578660d0600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b8673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62898960405161290c929190614ebb565b60405180910390a4612922838989858589612f4e565b612930838989898989612bc2565b5050505050505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600060146000369050101580156129c057506129bf33610b21565b5b156129d457601436033560601c90506129d8565b3390505b90565b6129fa8473ffffffffffffffffffffffffffffffffffffffff16612da9565b15612bba578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b8152600401612a40959493929190614f39565b602060405180830381600087803b158015612a5a57600080fd5b505af1925050508015612a8b57506040513d601f19601f82011682018060405250810190612a889190614fb6565b60015b612b3157612a97614ff0565b806308c379a01415612af45750612aac615012565b80612ab75750612af6565b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aeb9190613356565b60405180910390fd5b505b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b289061511a565b60405180910390fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612bb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612baf906151ac565b60405180910390fd5b505b505050505050565b612be18473ffffffffffffffffffffffffffffffffffffffff16612da9565b15612da1578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401612c279594939291906151cc565b602060405180830381600087803b158015612c4157600080fd5b505af1925050508015612c7257506040513d601f19601f82011682018060405250810190612c6f9190614fb6565b60015b612d1857612c7e614ff0565b806308c379a01415612cdb5750612c93615012565b80612c9e5750612cdd565b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cd29190613356565b60405180910390fd5b505b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d0f9061511a565b60405180910390fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612d9f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d96906151ac565b60405180910390fd5b505b505050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600060019054906101000a900460ff16612e1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e1290614bba565b60405180910390fd5b612e2481612f56565b50565b8060c960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600060019054906101000a900460ff16612eba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eb190614bba565b60405180910390fd5b612eca612ec5611bd1565b6121a9565b565b60606000600167ffffffffffffffff811115612eeb57612eea6133e6565b5b604051908082528060200260200182016040528015612f195781602001602082028036833780820191505090505b5090508281600081518110612f3157612f306143c8565b5b60200260200101818152505080915050919050565b505050505050565b505050505050565b8060679080519060200190612f6c929190612ff6565b5050565b828054612f7c90614304565b90600052602060002090601f016020900481019282612f9e5760008555612fe5565b82601f10612fb757803560ff1916838001178555612fe5565b82800160010185558215612fe5579182015b82811115612fe4578235825591602001919060010190612fc9565b5b509050612ff2919061307c565b5090565b82805461300290614304565b90600052602060002090601f016020900481019282613024576000855561306b565b82601f1061303d57805160ff191683800117855561306b565b8280016001018555821561306b579182015b8281111561306a57825182559160200191906001019061304f565b5b509050613078919061307c565b5090565b5b8082111561309557600081600090555060010161307d565b5090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006130d8826130ad565b9050919050565b6130e8816130cd565b81146130f357600080fd5b50565b600081359050613105816130df565b92915050565b6000819050919050565b61311e8161310b565b811461312957600080fd5b50565b60008135905061313b81613115565b92915050565b60008060408385031215613158576131576130a3565b5b6000613166858286016130f6565b92505060206131778582860161312c565b9150509250929050565b61318a8161310b565b82525050565b60006020820190506131a56000830184613181565b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6131e0816131ab565b81146131eb57600080fd5b50565b6000813590506131fd816131d7565b92915050565b600060208284031215613219576132186130a3565b5b6000613227848285016131ee565b91505092915050565b60008115159050919050565b61324581613230565b82525050565b6000602082019050613260600083018461323c565b92915050565b61326f816130cd565b82525050565b600060208201905061328a6000830184613266565b92915050565b6000602082840312156132a6576132a56130a3565b5b60006132b48482850161312c565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156132f75780820151818401526020810190506132dc565b83811115613306576000848401525b50505050565b6000601f19601f8301169050919050565b6000613328826132bd565b61333281856132c8565b93506133428185602086016132d9565b61334b8161330c565b840191505092915050565b60006020820190508181036000830152613370818461331d565b905092915050565b6000806040838503121561338f5761338e6130a3565b5b600061339d8582860161312c565b92505060206133ae8582860161312c565b9150509250929050565b60006040820190506133cd6000830185613266565b6133da6020830184613181565b9392505050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61341e8261330c565b810181811067ffffffffffffffff8211171561343d5761343c6133e6565b5b80604052505050565b6000613450613099565b905061345c8282613415565b919050565b600067ffffffffffffffff82111561347c5761347b6133e6565b5b602082029050602081019050919050565b600080fd5b60006134a56134a084613461565b613446565b905080838252602082019050602084028301858111156134c8576134c761348d565b5b835b818110156134f157806134dd888261312c565b8452602084019350506020810190506134ca565b5050509392505050565b600082601f8301126135105761350f6133e1565b5b8135613520848260208601613492565b91505092915050565b600080fd5b600067ffffffffffffffff821115613549576135486133e6565b5b6135528261330c565b9050602081019050919050565b82818337600083830152505050565b600061358161357c8461352e565b613446565b90508281526020810184848401111561359d5761359c613529565b5b6135a884828561355f565b509392505050565b600082601f8301126135c5576135c46133e1565b5b81356135d584826020860161356e565b91505092915050565b600080600080600060a086880312156135fa576135f96130a3565b5b6000613608888289016130f6565b9550506020613619888289016130f6565b945050604086013567ffffffffffffffff81111561363a576136396130a8565b5b613646888289016134fb565b935050606086013567ffffffffffffffff811115613667576136666130a8565b5b613673888289016134fb565b925050608086013567ffffffffffffffff811115613694576136936130a8565b5b6136a0888289016135b0565b9150509295509295909350565b6000602082840312156136c3576136c26130a3565b5b60006136d1848285016130f6565b91505092915050565b600067ffffffffffffffff8211156136f5576136f46133e6565b5b602082029050602081019050919050565b6000613719613714846136da565b613446565b9050808382526020820190506020840283018581111561373c5761373b61348d565b5b835b81811015613765578061375188826130f6565b84526020840193505060208101905061373e565b5050509392505050565b600082601f830112613784576137836133e1565b5b8135613794848260208601613706565b91505092915050565b600080604083850312156137b4576137b36130a3565b5b600083013567ffffffffffffffff8111156137d2576137d16130a8565b5b6137de8582860161376f565b925050602083013567ffffffffffffffff8111156137ff576137fe6130a8565b5b61380b858286016134fb565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61384a8161310b565b82525050565b600061385c8383613841565b60208301905092915050565b6000602082019050919050565b600061388082613815565b61388a8185613820565b935061389583613831565b8060005b838110156138c65781516138ad8882613850565b97506138b883613868565b925050600181019050613899565b5085935050505092915050565b600060208201905081810360008301526138ed8184613875565b905092915050565b600080fd5b60008083601f8401126139105761390f6133e1565b5b8235905067ffffffffffffffff81111561392d5761392c6138f5565b5b6020830191508360208202830111156139495761394861348d565b5b9250929050565b60008083601f840112613966576139656133e1565b5b8235905067ffffffffffffffff811115613983576139826138f5565b5b60208301915083602082028301111561399f5761399e61348d565b5b9250929050565b600080600080604085870312156139c0576139bf6130a3565b5b600085013567ffffffffffffffff8111156139de576139dd6130a8565b5b6139ea878288016138fa565b9450945050602085013567ffffffffffffffff811115613a0d57613a0c6130a8565b5b613a1987828801613950565b925092505092959194509250565b60008060408385031215613a3e57613a3d6130a3565b5b6000613a4c8582860161312c565b9250506020613a5d858286016130f6565b9150509250929050565b600080fd5b600060408284031215613a8257613a81613a67565b5b81905092915050565b60008083601f840112613aa157613aa06133e1565b5b8235905067ffffffffffffffff811115613abe57613abd6138f5565b5b602083019150836001820283011115613ada57613ad961348d565b5b9250929050565b600080600080600080600060e0888a031215613b0057613aff6130a3565b5b6000613b0e8a828b01613a6c565b9750506040613b1f8a828b016130f6565b9650506060613b308a828b016130f6565b9550506080613b418a828b016130f6565b94505060a0613b528a828b016130f6565b93505060c088013567ffffffffffffffff811115613b7357613b726130a8565b5b613b7f8a828b01613a8b565b925092505092959891949750929550565b60008060208385031215613ba757613ba66130a3565b5b600083013567ffffffffffffffff811115613bc557613bc46130a8565b5b613bd185828601613a8b565b92509250509250929050565b613be681613230565b8114613bf157600080fd5b50565b600081359050613c0381613bdd565b92915050565b60008060408385031215613c2057613c1f6130a3565b5b6000613c2e858286016130f6565b9250506020613c3f85828601613bf4565b9150509250929050565b60008060408385031215613c6057613c5f6130a3565b5b6000613c6e858286016130f6565b9250506020613c7f858286016130f6565b9150509250929050565b6000819050919050565b6000613cae613ca9613ca4846130ad565b613c89565b6130ad565b9050919050565b6000613cc082613c93565b9050919050565b6000613cd282613cb5565b9050919050565b613ce281613cc7565b82525050565b6000602082019050613cfd6000830184613cd9565b92915050565b600061ffff82169050919050565b613d1a81613d03565b82525050565b6000604082019050613d356000830185613266565b613d426020830184613d11565b9392505050565b600080600080600060a08688031215613d6557613d646130a3565b5b6000613d73888289016130f6565b9550506020613d84888289016130f6565b9450506040613d958882890161312c565b9350506060613da68882890161312c565b925050608086013567ffffffffffffffff811115613dc757613dc66130a8565b5b613dd3888289016135b0565b9150509295509295909350565b600060408284031215613df657613df56130a3565b5b6000613e0484828501613a6c565b91505092915050565b7f455243313135353a2062616c616e636520717565727920666f7220746865207a60008201527f65726f2061646472657373000000000000000000000000000000000000000000602082015250565b6000613e69602b836132c8565b9150613e7482613e0d565b604082019050919050565b60006020820190508181036000830152613e9881613e5c565b9050919050565b600067ffffffffffffffff821115613eba57613eb96133e6565b5b613ec38261330c565b9050602081019050919050565b6000613ee3613ede84613e9f565b613446565b905082815260208101848484011115613eff57613efe613529565b5b613f0a8482856132d9565b509392505050565b600082601f830112613f2757613f266133e1565b5b8151613f37848260208601613ed0565b91505092915050565b600060208284031215613f5657613f556130a3565b5b600082015167ffffffffffffffff811115613f7457613f736130a8565b5b613f8084828501613f12565b91505092915050565b600081905092915050565b7f697066733a2f2f00000000000000000000000000000000000000000000000000600082015250565b6000613fca600783613f89565b9150613fd582613f94565b600782019050919050565b6000613feb826132bd565b613ff58185613f89565b93506140058185602086016132d9565b80840191505092915050565b7f2f00000000000000000000000000000000000000000000000000000000000000600082015250565b6000614047600183613f89565b915061405282614011565b600182019050919050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000600082015250565b6000614093600583613f89565b915061409e8261405d565b600582019050919050565b60006140b482613fbd565b91506140c08285613fe0565b91506140cb8261403a565b91506140d78284613fe0565b91506140e282614086565b91508190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006141288261310b565b91506141338361310b565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561416c5761416b6140ee565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006141b18261310b565b91506141bc8361310b565b9250826141cc576141cb614177565b5b828204905092915050565b7f455243313135353a207472616e736665722063616c6c6572206973206e6f742060008201527f6f776e6572206e6f7220617070726f7665640000000000000000000000000000602082015250565b60006142336032836132c8565b915061423e826141d7565b604082019050919050565b6000602082019050818103600083015261426281614226565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061429f6020836132c8565b91506142aa82614269565b602082019050919050565b600060208201905081810360008301526142ce81614292565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061431c57607f821691505b602082108114156143305761432f6142d5565b5b50919050565b7f455243313135353a206163636f756e747320616e6420696473206c656e67746860008201527f206d69736d617463680000000000000000000000000000000000000000000000602082015250565b60006143926029836132c8565b915061439d82614336565b604082019050919050565b600060208201905081810360008301526143c181614385565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006144028261310b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415614435576144346140ee565b5b600182019050919050565b6000819050919050565b600060ff82169050919050565b600061447261446d61446884614440565b613c89565b61444a565b9050919050565b61448281614457565b82525050565b600060208201905061449d6000830184614479565b92915050565b60006144af83856132c8565b93506144bc83858461355f565b6144c58361330c565b840190509392505050565b60008190508160005260206000209050919050565b600081546144f281614304565b6144fc81866132c8565b9450600182166000811461451757600181146145295761455c565b60ff198316865260208601935061455c565b614532856144d0565b60005b8381101561455457815481890152600182019150602081019050614535565b808801955050505b50505092915050565b600060408201905081810360008301526145808185876144a3565b9050818103602083015261459481846144e5565b9050949350505050565b7f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260008201527f20617070726f7665640000000000000000000000000000000000000000000000602082015250565b60006145fa6029836132c8565b91506146058261459e565b604082019050919050565b60006020820190508181036000830152614629816145ed565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061468c6026836132c8565b915061469782614630565b604082019050919050565b600060208201905081810360008301526146bb8161467f565b9050919050565b60006060820190506146d76000830186613266565b6146e46020830185613266565b6146f16040830184613266565b949350505050565b60006147048261310b565b915061470f8361310b565b925082821015614722576147216140ee565b5b828203905092915050565b60006147388261310b565b91506147438361310b565b92508261475357614752614177565b5b828206905092915050565b60006147698261310b565b91506147748361310b565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156147a9576147a86140ee565b5b828201905092915050565b7f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060008201527f6d69736d61746368000000000000000000000000000000000000000000000000602082015250565b60006148106028836132c8565b915061481b826147b4565b604082019050919050565b6000602082019050818103600083015261483f81614803565b9050919050565b7f455243313135353a207472616e7366657220746f20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b60006148a26025836132c8565b91506148ad82614846565b604082019050919050565b600060208201905081810360008301526148d181614895565b9050919050565b7f455243313135353a20696e73756666696369656e742062616c616e636520666f60008201527f72207472616e7366657200000000000000000000000000000000000000000000602082015250565b6000614934602a836132c8565b915061493f826148d8565b604082019050919050565b6000602082019050818103600083015261496381614927565b9050919050565b600060408201905081810360008301526149848185613875565b905081810360208301526149988184613875565b90509392505050565b60006040820190506149b66000830185613266565b6149c36020830184613266565b9392505050565b7f455243313135353a206d696e7420746f20746865207a65726f2061646472657360008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b6000614a266021836132c8565b9150614a31826149ca565b604082019050919050565b60006020820190508181036000830152614a5581614a19565b9050919050565b6000614a77614a72614a6d84614440565b613c89565b61310b565b9050919050565b614a8781614a5c565b82525050565b6000604082019050614aa26000830185613181565b614aaf6020830184614a7e565b9392505050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b6000614b12602e836132c8565b9150614b1d82614ab6565b604082019050919050565b60006020820190508181036000830152614b4181614b05565b9050919050565b7f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960008201527f6e697469616c697a696e67000000000000000000000000000000000000000000602082015250565b6000614ba4602b836132c8565b9150614baf82614b48565b604082019050919050565b60006020820190508181036000830152614bd381614b97565b9050919050565b614be381613d03565b8114614bee57600080fd5b50565b600081359050614c0081614bda565b92915050565b600060208284031215614c1c57614c1b6130a3565b5b6000614c2a84828501614bf1565b91505092915050565b6000602082019050614c486000830184613d11565b92915050565b6000608082019050614c636000830187613266565b614c706020830186613d11565b614c7d6040830185613266565b614c8a6060830184613d11565b95945050505050565b60008135614ca0816130df565b80915050919050565b60008160001b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff614cd684614ca9565b9350801983169250808416831791505092915050565b6000614cf782613cb5565b9050919050565b6000819050919050565b614d1182614cec565b614d24614d1d82614cfe565b8354614cb6565b8255505050565b60008135614d3881614bda565b80915050919050565b60008160a01b9050919050565b600075ffff0000000000000000000000000000000000000000614d7084614d41565b9350801983169250808416831791505092915050565b6000614da1614d9c614d9784613d03565b613c89565b613d03565b9050919050565b6000819050919050565b614dbb82614d86565b614dce614dc782614da8565b8354614d4e565b8255505050565b600081016000830180614de781614c93565b9050614df38184614d08565b505050600081016020830180614e0881614d2b565b9050614e148184614db2565b5050505050565b614e258282614dd5565b5050565b7f455243313135353a2073657474696e6720617070726f76616c2073746174757360008201527f20666f722073656c660000000000000000000000000000000000000000000000602082015250565b6000614e856029836132c8565b9150614e9082614e29565b604082019050919050565b60006020820190508181036000830152614eb481614e78565b9050919050565b6000604082019050614ed06000830185613181565b614edd6020830184613181565b9392505050565b600081519050919050565b600082825260208201905092915050565b6000614f0b82614ee4565b614f158185614eef565b9350614f258185602086016132d9565b614f2e8161330c565b840191505092915050565b600060a082019050614f4e6000830188613266565b614f5b6020830187613266565b8181036040830152614f6d8186613875565b90508181036060830152614f818185613875565b90508181036080830152614f958184614f00565b90509695505050505050565b600081519050614fb0816131d7565b92915050565b600060208284031215614fcc57614fcb6130a3565b5b6000614fda84828501614fa1565b91505092915050565b60008160e01c9050919050565b600060033d111561500f5760046000803e61500c600051614fe3565b90505b90565b600060443d1015615022576150a5565b61502a613099565b60043d036004823e80513d602482011167ffffffffffffffff821117156150525750506150a5565b808201805167ffffffffffffffff81111561507057505050506150a5565b80602083010160043d03850181111561508d5750505050506150a5565b61509c82602001850186613415565b82955050505050505b90565b7f455243313135353a207472616e7366657220746f206e6f6e204552433131353560008201527f526563656976657220696d706c656d656e746572000000000000000000000000602082015250565b60006151046034836132c8565b915061510f826150a8565b604082019050919050565b60006020820190508181036000830152615133816150f7565b9050919050565b7f455243313135353a204552433131353552656365697665722072656a6563746560008201527f6420746f6b656e73000000000000000000000000000000000000000000000000602082015250565b60006151966028836132c8565b91506151a18261513a565b604082019050919050565b600060208201905081810360008301526151c581615189565b9050919050565b600060a0820190506151e16000830188613266565b6151ee6020830187613266565b6151fb6040830186613181565b6152086060830185613181565b818103608083015261521a8184614f00565b9050969550505050505056fea26469706673582212206c7042a23df7cccb75e06ba03378ce9dfda478e5fe86bb5ca84873e97d9afe1764736f6c63430008090033
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.