Token Soulbound Card
Overview ERC-721
Total Supply:
5 SCARD
Holders:
4 addresses
Transfers:
-
Profile Summary
Contract:
[ Download CSV Export ]
[ Download CSV Export ]
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
SoulboundCard
Compiler Version
v0.8.4+commit.c7e474f2
Contract Source Code (Solidity Multiple files format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./BusinessCard.sol"; import "./Ownable.sol"; import "./IERC721.sol"; import "./IERC721Enumerable.sol"; import "./IERC721Metadata.sol"; import "./Address.sol"; import "./Strings.sol"; import "./ERC165Storage.sol"; import "./SafeMath.sol"; import "./EnumerableSet.sol"; contract SoulboundCard is ERC165Storage, IERC721, IERC721Metadata, IERC721Enumerable, Ownable { using SafeMath for uint256; using Address for address; using EnumerableSet for EnumerableSet.UintSet; using EnumerableSet for EnumerableSet.AddressSet; using Strings for uint256; // Mapping from address to their (enumerable) set of received Soulbound Cards mapping (address => EnumerableSet.UintSet) private _receivedTokens; // Mapping from token IDs to their (enumerable) set of receiver addresses mapping (uint256 => EnumerableSet.AddressSet) private _tokenReceivers; // Mapping of addresses that have blakclisted the receiving of Soulbound Cards mapping (address => bool) private _blacklistedReceivers; // Token name string private _name; // Token symbol string private _symbol; // Main Business Card smart contract BusinessCard bCard; constructor (string memory name_, string memory symbol_, address _bCard) { _name = name_; _symbol = symbol_; bCard = BusinessCard(_bCard); // register the supported interfaces to conform to ERC721 via ERC165 /* * bytes4(keccak256('balanceOf(address)')) == 0x70a08231 * bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e * bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3 * bytes4(keccak256('getApproved(uint256)')) == 0x081812fc * bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465 * bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5 * bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde * * => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^ * 0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd */ _registerInterface(0x80ac58cd); /* * bytes4(keccak256('name()')) == 0x06fdde03 * bytes4(keccak256('symbol()')) == 0x95d89b41 * bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd * * => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f */ _registerInterface(0x5b5e139f); /* * bytes4(keccak256('totalSupply()')) == 0x18160ddd * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59 * bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7 * * => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63 */ _registerInterface(0x780e9d63); } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Sends a copy of the Business Card specified by tokenId as a Soulbound Card to the * specified address */ function sendSoulboundCard(address from, address receiver, uint256 tokenId) external { require(_isApprovedOrOwner(msg.sender, tokenId), "SCARD: caller is not owner nor approved"); require(bCard.ownerOf(tokenId) == from, "SCARD: sending card that is not own"); require(receiver != address(0), "SCARD: sending to zero address"); require(receiver != from, "SCARD: sending to owner"); require(!_blacklistedReceivers[receiver], "SCARD: receiver blacklisted themselves"); require(!_receivedTokens[receiver].contains(tokenId), "SCARD: receiver was already sent the Soulbound Card"); _receivedTokens[receiver].add(tokenId); _tokenReceivers[tokenId].add(receiver); emit Transfer(from, receiver, tokenId); } /** * @dev Burns a specific Soulbound Card that was sent to msg.sender */ function burnSoulboundCard(address receiver, uint256 toBurn) external { require( msg.sender == receiver || _isApprovedOrOwner(msg.sender, toBurn), "SCARD: caller is not owner nor approved" ); require(_receivedTokens[receiver].contains(toBurn), "SCARD: token not in receiver's list"); _burnSoulboundCard(receiver, toBurn); } /** * @dev Burns a specific Soulbound Card that was sent to msg.sender */ function _burnSoulboundCard(address receiver, uint256 toBurn) internal { require( // Remove the Soulbound Card from the set of tokens address `receiver` received _receivedTokens[receiver].remove(toBurn) && // Remove the address `receiver` from the set of receivers for the Soulbound Card `tokenId` _tokenReceivers[toBurn].remove(receiver) , "SCARD: token not on the set" ); emit Transfer(receiver, address(0), toBurn); } /** * @dev Burns the specified Soulbound Cards associated with a Business Card `tokenId` */ function burnSoulboundCardsOfToken(uint256 tokenId, address[] calldata toBurn) external { require( msg.sender == address(bCard) || _isApprovedOrOwner(msg.sender, tokenId), "SCARD: caller is not BCARD contract nor owner nor approved" ); // To clean an EnumerableSet, we remove all elements one by one for (uint256 i = 0; i < toBurn.length; i++) { address receiver = toBurn[i]; _burnSoulboundCard(receiver, tokenId); } } /** * @dev Burns the specified Soulbound Cards associated with a Business Card `tokenId` */ function burnAllSoulboundCardsOfToken(uint256 tokenId) external { require( msg.sender == address(bCard) || _isApprovedOrOwner(msg.sender, tokenId), "SCARD: caller is not BCARD contract nor owner nor approved" ); // To clean an EnumerableSet, we remove all elements one by one address[] memory toBurn = _tokenReceivers[tokenId].values(); for (uint256 i = 0; i < toBurn.length; i++) { address receiver = toBurn[i]; _burnSoulboundCard(receiver, tokenId); } } /** * @dev Burns all the Soulbound Cards that were sent to the specified address `toDisable` * Caller must be the specified address or an approved operator */ function burnReceivedSoulboundCards(address receiver, uint256[] calldata toBurn) external { require( msg.sender == receiver || isApprovedForAll(receiver, msg.sender) , "SCARD: caller is not receiver nor approved for all" ); // To clean an EnumerableSet, we remove all elements one by one for (uint256 i = 0; i < toBurn.length; ++i) { uint256 cardId = toBurn[i]; _burnSoulboundCard(receiver, cardId); } } /** * @dev Blacklists the specified address from receiving any additional sCards * Caller must be the specified address or an approved operator */ function disableSoulboundCardsForAddress(address toDisable) external { require(msg.sender == toDisable || isApprovedForAll(toDisable, msg.sender), "SCARD: caller is not owner nor approved for all"); _blacklistedReceivers[toDisable] = true; } /** * @dev Returns if address `receiver` is blacklisted from getting Soulbound Cards */ function isBlacklisted(address receiver) external view returns (bool blacklisted) { blacklisted = _blacklistedReceivers[receiver]; } /** * @dev Returns the Soulbound Card tokenURI, which is linked to the Business Card tokenURI */ function tokenURI(uint256 tokenId) external view override returns (string memory) { return bCard.tokenURI(tokenId); } /** * @dev See {IERC721-ownerOf}. * * Here owner represents ownership of the original Business Card */ function ownerOf(uint256 _tokenId) public view virtual override returns (address) { return bCard.ownerOf(_tokenId); } /** * @dev See {IERC721-balanceOf}. * * Returns the number of Soulbound Cards received by an address */ function balanceOf(address _owner) public view virtual override returns (uint256) { require(_owner != address(0), "ERC721: balance query for the zero address"); return _receivedTokens[_owner].length(); } /** * @dev See {IERC721Enumerable-totalSupply}. * * The `totalSupply` is defined as the number of Soulbound Cards that have been sent */ function totalSupply() public view virtual override returns (uint256 count) { uint256 nTokens = bCard.totalSupply(); for (uint256 i = 1; i <= nTokens; ++i) { count += _tokenReceivers[i].length(); } } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. * * Returns the Soulbound Card received by an address at a given index */ function tokenOfOwnerByIndex(address _owner, uint256 index) public view virtual override returns (uint256) { require(index < balanceOf(_owner), "Index out of bounds"); return _receivedTokens[_owner].at(index); } /** * @dev Returns the list of addresses that received a copy of a given `tokenId` Business Card * as a Soulbound Card */ function soulboundCardReceivers(uint256 tokenId) public view returns (address[] memory) { return _tokenReceivers[tokenId].values(); } /** * @dev Returns the list of Soulbound Cards that an address `receiver` got */ function receivedSoulboundCards(address receiver) public view returns (uint256[] memory) { return _receivedTokens[receiver].values(); } /** * @dev See {IERC721Enumerable-tokenByIndex}. * * Returns the corresponding Business Card by index */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { return bCard.tokenByIndex(index); } /** * @dev See {IERC721-approve}. * * Only present to be ERC721 compliant. Soulbound Cards cannot be approved for spending * as they are not transferable. Granting the corresponding Business Card approval for * spending also allows them to send Soulbound Cards. */ function approve(address /* _approved */, uint256 /* _tokenId */) public pure virtual override { revert("SCARD: cannot approve Soulbound Cards"); } /** * @dev See {IERC721-getApproved}. * * Returns the address that is approved to spend the BusinessCard `tokenId`. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { return bCard.getApproved(tokenId); } /** * @dev See {IERC721-setApprovalForAll}. * * Only present to be ERC721 compliant. Soulbound Cards cannot be approved for spending * as they are not transferable. Granting the corresponding Business Card approval for * spending also allows them to send Soulbound Cards. */ function setApprovalForAll(address /* _operator */, bool /* _approved */) public pure virtual override { revert("SCARD: cannot approve Soulbound Cards"); } /** * @dev See {IERC721-isApprovedForAll}. * * Returns if an address is approved to spend any of the `owner`'s Business Cards. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return bCard.isApprovedForAll(owner, operator); } /** * @dev See {IERC721-transferFrom}. * * Only present to be ERC721 compliant. Soulbound Cards cannot be transferred. They can * be sent by the Business Card owner or approved address, and can be burned by either * the recipient or Business Card owner or approved address. */ function transferFrom(address /* from */, address /* to */, uint256 /* tokenId */) public pure virtual override { revert("SCARD: cannot transfer Soulbound Cards"); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. * * Only present to be ERC721 compliant. Soulbound Cards cannot be transferred. They can * be sent by the Business Card owner or approved address, and can be burned by either * the recipient or Business Card owner or approved address. */ function safeTransferFrom(address /* from */, address /* to */, uint256 /* tokenId */, bytes memory /* _data */) public pure virtual override { revert("SCARD: cannot transfer Soulbound Cards"); } /** * @dev Returns whether `spender` is allowed to manage the BusinessCard `tokenId`. * * Requirements: * * - A Business Card by `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = bCard.ownerOf(tokenId); return (spender == owner || bCard.getApproved(tokenId) == spender || bCard.isApprovedForAll(owner, spender)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // Because every self-respected businessman needs his business card pragma solidity ^0.8.0; import "./BusinessCardUtils.sol"; import "./Ownable.sol"; import "./IERC721.sol"; import "./IERC721Enumerable.sol"; import "./IERC721Metadata.sol"; import "./IERC721Receiver.sol"; import "./Address.sol"; import "./Context.sol"; import "./Strings.sol"; import "./ERC165Storage.sol"; import "./SafeMath.sol"; import "./EnumerableMap.sol"; import "./EnumerableSet.sol"; contract ISoulboundCard { function burnAllSoulboundCardsOfToken(uint256 tokenId) external { } } /** * @title NFT Business Card smart contract * @dev compliant with https://eips.ethereum.org/EIPS/eip-721 */ contract BusinessCard is ERC165Storage, IERC721, IERC721Metadata, IERC721Enumerable, Ownable { using SafeMath for uint256; using Address for address; using EnumerableSet for EnumerableSet.UintSet; using EnumerableMap for EnumerableMap.UintToAddressMap; using Strings for uint256; // Mapping from holder address to their (enumerable) set of owned tokens mapping (address => EnumerableSet.UintSet) private _holderTokens; // Enumerable mapping from token ids to their owners EnumerableMap.UintToAddressMap private _tokenOwners; // Mapping from token ID to approved address mapping (uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping (address => mapping (address => bool)) private _operatorApprovals; // Token name string private _name; // Token symbol string private _symbol; // Mapping for token URIs mapping (uint256 => string) private _tokenURIs; // Base URI string private _baseURI; // Public variables uint256 public constant maxSupply = 1111; bool public saleStarted; // Random nonce for generating genes uint256 private randNonce; struct Card { uint256 genes; string name; } // Mapping from token ID to genes mapping (uint256 => Card) private _tokenStats; // Mapping for reserved names, reserved names are stored in lowercase mapping (string => bool) private _nameReserved; // Values sent in the event when minting / updating a card // All the metadata attributes that do NOT get stored on chain struct CardProperties { string position; string twitterAccount; string telegramAccount; string telegramGroup; uint256 discordAccount; string discordGroup; string githubUsername; string website; } // Default URI string private _defaultURI; // Address of the oracle address private serverOracle; // Requests made to the NFT oracle mapping(uint256 => bool) public requests; // Marketplace address address private bCardMarketplace; // sCard address - SoulboundCards ISoulboundCard private sCard; // Token mint price uint256 public mintPrice = 0.1 ether; // Token URI update / swap price uint256 public updatePrice = 0.05 ether; // Oracle update transaction gas price uint256 public oraclePrice = 0.015 ether; // Oracle related events event UpdateRequest(uint256 tokenId, uint256 genes, string name, CardProperties cardProperties); event SwapRequest(uint256 tokenId1, uint256 tokenId2, uint256 genes1, uint256 genes2); event TokenURIUpdated(uint256 tokenId, string tokenURI); /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection, and defining base and default URIs. */ constructor (string memory name_, string memory symbol_, string memory baseURI_, string memory defaultURI_) { _name = name_; _symbol = symbol_; _baseURI = baseURI_; _defaultURI = defaultURI_; // register the supported interfaces to conform to ERC721 via ERC165 /* * bytes4(keccak256('balanceOf(address)')) == 0x70a08231 * bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e * bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3 * bytes4(keccak256('getApproved(uint256)')) == 0x081812fc * bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465 * bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5 * bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde * * => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^ * 0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd */ _registerInterface(0x80ac58cd); /* * bytes4(keccak256('name()')) == 0x06fdde03 * bytes4(keccak256('symbol()')) == 0x95d89b41 * bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd * * => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f */ _registerInterface(0x5b5e139f); /* * bytes4(keccak256('totalSupply()')) == 0x18160ddd * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59 * bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7 * * => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63 */ _registerInterface(0x780e9d63); } /** * @dev Sets up a new oracle that handles the dynamic aspect of the NFT */ function setOracle(address _serverOracle) external onlyOwner { serverOracle = _serverOracle; } /** * @dev Sets up a Marketplace allowing the native trading of Business Cards */ function setMarketplace(address _marketplace) external onlyOwner { bCardMarketplace = _marketplace; } /** * @dev Sets up the sCard address for interaction */ function setSoulboundCard(address _soulbound) external onlyOwner { sCard = ISoulboundCard(_soulbound); } /** * @dev Changes the update price for the usage of the oracle */ function modifyUpdatePrice(uint256 newUpdatePrice) external onlyOwner { require(newUpdatePrice >= oraclePrice); // dev: Update price must always cover the gas costs of running the oracle updatePrice = newUpdatePrice; } /** * @dev Calls the oracle to update a certain token URI with the newly defined Card struct */ function _updateTokenURI(uint256 _tokenId, uint256 _genes, string calldata _cardName, CardProperties calldata _cardProperties) internal { require(BusinessCardUtils.validateOtherProperties(_cardProperties)); // Other properties are not valid require(_exists(_tokenId)); // Calls for updating the token can only be made if it is not being processed already require(requests[_tokenId] == false, "Update being processed"); requests[_tokenId] = true; // Fund the server oracle with enough funds for the updateCallback transaction payable(serverOracle).transfer(oraclePrice); // Emit event to be catched by the server oracle running off-chain emit UpdateRequest(_tokenId, _genes, _cardName, _cardProperties); } /** * @dev Updates a certain token URI and clears the corresponding update request * Only the assigned server oracle is allowed to call this function */ function updateCallback(uint256 _tokenId, string memory _tokenURI) external { _callback(_tokenId, _tokenURI); } /** * @dev Updates a certain token URI and clears the corresponding update request * Only the assigned server oracle is allowed to call this function */ function swapCallback(uint256 _tokenId1, uint256 _tokenId2, string memory _tokenURI1, string memory _tokenURI2) external { _callback(_tokenId1, _tokenURI1); _callback(_tokenId2, _tokenURI2); } /** * @dev Updates a certain token URI and clears the corresponding update request * Only the assigned server oracle is allowed to call this function */ function _callback(uint256 _tokenId, string memory _tokenURI) internal { require(_msgSender() == serverOracle); // dev: Only the assigned oracle can call this function require(requests[_tokenId]); // dev: Request not in pending list _tokenURIs[_tokenId] = _tokenURI; delete requests[_tokenId]; emit TokenURIUpdated(_tokenId, _tokenURI); } /** * @dev Mints a new NFT Business Card */ function getCard(string calldata _cardName, CardProperties calldata _cardProperties) public payable { require(saleStarted == true); // dev: sale not started or paused, can be managed on frontend require(totalSupply() < maxSupply); // dev: sale has ended, can be managed on frontend require(msg.value >= mintPrice); // dev: value sent is below the price, can be managed on frontend // Minting a new NFT with the name and position provided _safeMint(_msgSender(), totalSupply() + 1, _cardName, _cardProperties); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: d* * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address _to, uint256 _tokenId, string calldata _cardName, CardProperties calldata _cardProperties) internal virtual { require( BusinessCardUtils.validateName(_cardName) && isNameReserved(_cardName) == false, "Name taken or not valid" ); require( BusinessCardUtils.validatePosition(_cardProperties.position), "Position not valid" ); // Generating the random genes, defined by a 26 digit number // The server oracle will convert the genes to a string and add leading zeros, as tokenURIs are generated with this constraint uint256 genes = uint(keccak256(abi.encodePacked(block.timestamp, msg.sender, _cardName, randNonce))) % 10**30; randNonce++; // Generating a new card toggleReserveName(_cardName, true); _tokenStats[_tokenId] = Card(genes, _cardName); _safeMint(_to, _tokenId, abi.encodePacked(_cardName, genes)); _updateTokenURI(_tokenId, genes, _cardName, _cardProperties); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual { _mint(to, tokenId); require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Changes the name and/or position of a given NFT, must be owned by the caller. * Whenever such change is made, it is first immediately reflected in the Card struct, and in the metadata after oracle updates. * User can change both name and position, just the name, or just the position (by leaving those inputs empty) */ function updateCard(uint256 tokenId, string calldata newName, CardProperties calldata newCardProperties) public payable { require(saleStarted == true); // dev: updates paused, can be managed on frontend require(_isApprovedOrOwner(_msgSender(), tokenId), "Caller is not owner nor approved"); require( isNameReserved(newName) == false && ( bytes(newName).length == 0 || BusinessCardUtils.validateName(newName) == true ) , "Name taken or not valid" ); require( bytes(newCardProperties.position).length == 0 || BusinessCardUtils.validatePosition(newCardProperties.position) == true , "Position not valid" ); require( msg.value >= updatePrice || _msgSender() == bCardMarketplace ); // dev: value sent is below the price, can be managed on frontend // Only change the name if specified if (bytes(newName).length > 0) { // De-reserve the old name toggleReserveName(_tokenStats[tokenId].name, false); // Reserve the new name toggleReserveName(newName, true); // Changing the token name _tokenStats[tokenId].name = newName; } // Make new tokenURI update request _updateTokenURI(tokenId, _tokenStats[tokenId].genes, newName, newCardProperties); } /** * @dev Swaps the name and position between two NFTs, must be owned by the caller. * This is to give customers the ability to directly shuffle name and positions of their * cards, and prevent possible "name snipers" */ function swapCards(uint256 tokenId1, uint256 tokenId2) public payable { require(saleStarted == true); // dev: updates paused, can be managed on frontend require( _isApprovedOrOwner(_msgSender(), tokenId1) && _isApprovedOrOwner(_msgSender(), tokenId2), "Caller is not owner nor approved" ); require(msg.value >= updatePrice); // dev: value sent is below the price, can be managed on frontend // Calls for updating the token can only be made if it is not being processed already require(requests[tokenId1] == false && requests[tokenId2] == false, "Update being processed"); // Swapping names between tokens string memory name1 = _tokenStats[tokenId1].name; _tokenStats[tokenId1].name = _tokenStats[tokenId2].name; _tokenStats[tokenId2].name = name1; // Requests now pending requests[tokenId1] = true; requests[tokenId2] = true; // Emitting a single swap request to the oracle -- processed differently emit SwapRequest(tokenId1, tokenId2, _tokenStats[tokenId1].genes, _tokenStats[tokenId2].genes); // Fund the server oracle with enough funds for the swapCallback transaction payable(serverOracle).transfer(oraclePrice); } /** * @dev Updates the tokenURI, intented to be used only when oracle fails to update a tokenURI */ function updateTokenURI(uint256 tokenId, string calldata cardName, CardProperties calldata _cardProperties) external onlyOwner { _updateTokenURI(tokenId, _tokenStats[tokenId].genes, cardName, _cardProperties); } /** * @dev Starts the sale, cannot do so until the oracle is defined */ function startSale() external onlyOwner { require(serverOracle != address(0)); // dev: Oracle not defined saleStarted = true; } /** * @dev Pauses the sale */ function pauseSale() external onlyOwner { saleStarted = false; } /** * @dev Returns the stats of a token */ function tokenStats(uint256 tokenId) public view returns (Card memory) { return _tokenStats[tokenId]; } /** * @dev Overrides the default tokenURI behaviour to include the default URI */ function tokenURI(uint256 tokenId) external view override returns (string memory) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); string memory token = _tokenURIs[tokenId]; // If there is no tokenURI, returns the defaultURI, which must be defined after deployment if (bytes(token).length == 0) { return string(abi.encodePacked( baseURI(), defaultURI() )); } else { return string(abi.encodePacked( baseURI(), token )); } } /** * @dev For setting the baseURI for all tokenId's. */ function setBaseURI(string memory newBaseURI) external onlyOwner { require(bytes(newBaseURI).length > 0); _baseURI = newBaseURI; } /** * @dev Returns the default URI set via {_setBaseURI}. This will be * automatically added as a prefix in {tokenURI} to each token's URI, or * to the token ID if no specific URI is set for that token ID. */ function defaultURI() public view virtual returns (string memory) { return _defaultURI; } /** * @dev For setting the default URI for all tokenId's. */ function setDefaultURI(string calldata newDefaultURI) external onlyOwner { require(bytes(newDefaultURI).length > 0); // dev: cannot be set to empty string _defaultURI = newDefaultURI; } /** * @dev Returns if the name has been reserved. * Name reservation checks are made in lowercase */ function isNameReserved(string calldata nameString) public view returns (bool) { return _nameReserved[BusinessCardUtils.toLower(nameString)]; } /** * @dev Reserves the name if isReserve is set to true, de-reserves if set to false * Names are reserved in lowercase, but stored in whatever case the user gave */ function toggleReserveName(string memory str, bool isReserve) internal { _nameReserved[BusinessCardUtils.toLower(str)] = isReserve; } /** * @dev Withdraw balance from this contract (Callable by owner) */ function withdraw() onlyOwner external { uint balance = address(this).balance; payable(msg.sender).transfer(balance); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: balance query for the zero address"); return _holderTokens[owner].length(); } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token"); } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the base URI set via {_setBaseURI}. This will be * automatically added as a prefix in {tokenURI} to each token's URI, or * to the token ID if no specific URI is set for that token ID. */ function baseURI() public view virtual returns (string memory) { return _baseURI; } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < balanceOf(owner)); // @dev: index out of bounds return _holderTokens[owner].at(index); } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds return _tokenOwners.length(); } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < totalSupply()); // @dev: index out of bounds (uint256 tokenId, ) = _tokenOwners.at(index); return tokenId; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { require(_exists(tokenId), "ERC721: approved query for nonexistent token"); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { require(operator != _msgSender(), "ERC721: approve to caller"); _operatorApprovals[_msgSender()][operator] = approved; emit ApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. * * If the sCard smart contract was specified, it burns all Soulbound Cards associated * with the Business Card `tokenId` in the process */ function transferFrom(address from, address to, uint256 tokenId) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _transfer(from, to, tokenId, true); } /** * @dev Works as `transferFrom`, but will not burn the associated Soulbound Cards */ function transferFromWithoutBurn(address from, address to, uint256 tokenId) public virtual { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _transfer(from, to, tokenId, false); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _safeTransfer(from, to, tokenId, _data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `_data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual { _transfer(from, to, tokenId, true); require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _tokenOwners.contains(tokenId); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { require(_exists(tokenId), "ERC721: operator query for nonexistent token"); address owner = ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address _to, uint256 _tokenId) internal virtual { require(_to != address(0), "ERC721: mint to the zero address"); require(!_exists(_tokenId), "ERC721: token already minted"); _holderTokens[_to].add(_tokenId); _tokenOwners.set(_tokenId, _to); emit Transfer(address(0), _to, _tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer(address from, address to, uint256 tokenId, bool burn) internal virtual { require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); // internal owner require(to != address(0), "ERC721: transfer to the zero address"); // Burn the associated Soulbound Cards if (address(sCard) != address(0) && burn) { sCard.burnAllSoulboundCardsOfToken(tokenId); } // Clear approvals from the previous owner _approve(address(0), tokenId); _holderTokens[from].remove(tokenId); _holderTokens[to].add(tokenId); _tokenOwners.set(tokenId, to); emit Transfer(from, to, tokenId); } /** * @dev Approve `to` to operate on `tokenId` * * Emits a {Approval} event. */ function _approve(address to, uint256 tokenId) private { _tokenApprovals[tokenId] = to; emit Approval(ownerOf(tokenId), to, tokenId); // internal owner } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) private returns (bool) { if (!to.isContract()) { return true; } bytes memory returndata = to.functionCall(abi.encodeWithSelector( IERC721Receiver(to).onERC721Received.selector, _msgSender(), from, tokenId, _data ), "ERC721: transfer to non ERC721Receiver implementer"); bytes4 retval = abi.decode(returndata, (bytes4)); return (retval == 0x150b7a02); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./BusinessCard.sol"; /** * @dev Useful functions for validating the name and position of Business Cards */ library BusinessCardUtils { /** * @dev Check if the name string is valid: * Alphanumeric and spaces without leading or trailing space, with maximum characters * Must contain at most one space, ensuring a Name SURNAME input. */ function validateName(string calldata str) internal pure returns (bool) { bytes memory b = bytes(str); // String length requirements if( b.length == 0 || b.length > 22 || b[0] == 0x20 || b[b.length - 1] == 0x20 ) return false; // Characters check require(validateString(str), "Non valid characters"); // Name is validated return true; } /** * @dev Check if the position string is valid: * Alphanumeric and spaces without leading or trailing space, with maximum characters */ function validatePosition(string calldata str) internal pure returns (bool) { bytes memory b = bytes(str); // String length requirements if( b.length == 0 || b.length > 32 || b[0] == 0x20 || b[b.length - 1] == 0x20 ) return false; // Characters check require(validateString(str), "Non valid characters"); // Position is validated return true; } /** * @dev Validates that string contains valid characters, alphanumerical and some special symbols */ function validateString(string calldata str) internal pure returns (bool) { bytes memory b = bytes(str); bytes1 lastChar = b[0]; for(uint i; i<b.length; ++i){ bytes1 char = b[i]; if (char == 0x20 && lastChar == 0x20) return false; // Cannot contain continuous spaces if( !(char >= 0x20 && char <= 0x3F) && // Special characters and numbers !(char >= 0x41 && char <= 0x5A) && // A-Z !(char >= 0x61 && char <= 0x7A) // a-z ) return false; lastChar = char; } return true; } function validateOtherProperties(BusinessCard.CardProperties calldata cardProperties) internal pure returns (bool) { if( bytes(cardProperties.twitterAccount).length < 15 && bytes(cardProperties.telegramAccount).length < 32 && bytes(cardProperties.telegramGroup).length < 32 && ((cardProperties.discordAccount >= 10**17 && cardProperties.discordAccount < 10**18) || cardProperties.discordAccount == 0) && bytes(cardProperties.discordGroup).length < 32 && bytes(cardProperties.githubUsername).length < 39 && bytes(cardProperties.website).length < 50 ) return true; return false; } /** * @dev Converts the string to lowercase */ function toLower(string memory str) internal pure returns (string memory){ bytes memory bStr = bytes(str); bytes memory bLower = new bytes(bStr.length); for (uint i = 0; i < bStr.length; ++i) { // Uppercase character if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) { bLower[i] = bytes1(uint8(bStr[i]) + 32); } else { bLower[i] = bStr[i]; } } return string(bLower); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableMap.sol) pragma solidity ^0.8.0; import "./EnumerableSet.sol"; /** * @dev Library for managing an enumerable variant of Solidity's * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] * type. * * Maps have the following properties: * * - Entries are added, removed, and checked for existence in constant time * (O(1)). * - Entries are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableMap for EnumerableMap.UintToAddressMap; * * // Declare a set state variable * EnumerableMap.UintToAddressMap private myMap; * } * ``` * * The following map types are supported: * * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 * - `address -> uint256` (`AddressToUintMap`) since v4.6.0 * - `bytes32 -> bytes32` (`Bytes32ToBytes32`) since v4.6.0 * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0 * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0 * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an array of EnumerableMap. * ==== */ library EnumerableMap { using EnumerableSet for EnumerableSet.Bytes32Set; // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Map type with // bytes32 keys and values. // The Map implementation uses private functions, and user-facing // implementations (such as Uint256ToAddressMap) are just wrappers around // the underlying Map. // This means that we can only create new EnumerableMaps for types that fit // in bytes32. struct Bytes32ToBytes32Map { // Storage of keys EnumerableSet.Bytes32Set _keys; mapping(bytes32 => bytes32) _values; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set( Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value ) internal returns (bool) { map._values[key] = value; return map._keys.add(key); } /** * @dev Removes a key-value pair from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) { delete map._values[key]; return map._keys.remove(key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) { return map._keys.contains(key); } /** * @dev Returns the number of key-value pairs in the map. O(1). */ function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) { return map._keys.length(); } /** * @dev Returns the key-value pair stored at position `index` in the map. O(1). * * Note that there are no guarantees on the ordering of entries inside the * array, and it may change when more entries are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) { bytes32 key = map._keys.at(index); return (key, map._values[key]); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) { bytes32 value = map._values[key]; if (value == bytes32(0)) { return (contains(map, key), bytes32(0)); } else { return (true, value); } } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) { bytes32 value = map._values[key]; require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key"); return value; } /** * @dev Same as {_get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {_tryGet}. */ function get( Bytes32ToBytes32Map storage map, bytes32 key, string memory errorMessage ) internal view returns (bytes32) { bytes32 value = map._values[key]; require(value != 0 || contains(map, key), errorMessage); return value; } // UintToUintMap struct UintToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set( UintToUintMap storage map, uint256 key, uint256 value ) internal returns (bool) { return set(map._inner, bytes32(key), bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToUintMap storage map, uint256 key) internal returns (bool) { return remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) { return contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (uint256(key), uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) { return uint256(get(map._inner, bytes32(key))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( UintToUintMap storage map, uint256 key, string memory errorMessage ) internal view returns (uint256) { return uint256(get(map._inner, bytes32(key), errorMessage)); } // UintToAddressMap struct UintToAddressMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set( UintToAddressMap storage map, uint256 key, address value ) internal returns (bool) { return set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { return remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { return contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToAddressMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { (bytes32 key, bytes32 value) = at(map._inner, index); return (uint256(key), address(uint160(uint256(value)))); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. * * _Available since v3.4._ */ function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); return (success, address(uint160(uint256(value)))); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { return address(uint160(uint256(get(map._inner, bytes32(key))))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( UintToAddressMap storage map, uint256 key, string memory errorMessage ) internal view returns (address) { return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage)))); } // AddressToUintMap struct AddressToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set( AddressToUintMap storage map, address key, uint256 value ) internal returns (bool) { return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(AddressToUintMap storage map, address key) internal returns (bool) { return remove(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(AddressToUintMap storage map, address key) internal view returns (bool) { return contains(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns the number of elements in the map. O(1). */ function length(AddressToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (address(uint160(uint256(key))), uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(AddressToUintMap storage map, address key) internal view returns (uint256) { return uint256(get(map._inner, bytes32(uint256(uint160(key))))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( AddressToUintMap storage map, address key, string memory errorMessage ) internal view returns (uint256) { return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage)); } // Bytes32ToUintMap struct Bytes32ToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set( Bytes32ToUintMap storage map, bytes32 key, uint256 value ) internal returns (bool) { return set(map._inner, key, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) { return remove(map._inner, key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) { return contains(map._inner, key); } /** * @dev Returns the number of elements in the map. O(1). */ function length(Bytes32ToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (key, uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, key); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) { return uint256(get(map._inner, key)); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( Bytes32ToUintMap storage map, bytes32 key, string memory errorMessage ) internal view returns (uint256) { return uint256(get(map._inner, key, errorMessage)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.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 ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Storage.sol) pragma solidity ^0.8.0; import "./ERC165.sol"; /** * @dev Storage based implementation of the {IERC165} interface. * * Contracts may inherit from this and call {_registerInterface} to declare * their support of an interface. */ abstract contract ERC165Storage is ERC165 { /** * @dev Mapping of interface ids to whether or not it's supported. */ mapping(bytes4 => bool) private _supportedInterfaces; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return super.supportsInterface(interfaceId) || _supportedInterfaces[interfaceId]; } /** * @dev Registers the contract as an implementer of the interface defined by * `interfaceId`. Support of the actual ERC165 interface is automatic and * registering its interface id is not required. * * See {IERC165-supportsInterface}. * * Requirements: * * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). */ function _registerInterface(bytes4 interfaceId) internal virtual { require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); _supportedInterfaces[interfaceId] = 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 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "./Context.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 Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"address","name":"_bCard","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burnAllSoulboundCardsOfToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256[]","name":"toBurn","type":"uint256[]"}],"name":"burnReceivedSoulboundCards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"toBurn","type":"uint256"}],"name":"burnSoulboundCard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address[]","name":"toBurn","type":"address[]"}],"name":"burnSoulboundCardsOfToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"toDisable","type":"address"}],"name":"disableSoulboundCardsForAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"isBlacklisted","outputs":[{"internalType":"bool","name":"blacklisted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"receivedSoulboundCards","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"sendSoulboundCard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bool","name":"","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"soulboundCardReceivers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162003e3638038062003e368339818101604052810190620000379190620003fa565b620000576200004b6200011b60201b60201c565b6200012360201b60201c565b82600590805190602001906200006f929190620002c1565b50816006908051906020019062000088929190620002c1565b5080600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620000e26380ac58cd60e01b620001e960201b60201c565b620000fa635b5e139f60e01b620001e960201b60201c565b6200011263780e9d6360e01b620001e960201b60201c565b505050620006c3565b600033905090565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b63ffffffff60e01b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141562000255576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200024c90620004a9565b60405180910390fd5b6001600080837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b828054620002cf90620005a5565b90600052602060002090601f016020900481019282620002f357600085556200033f565b82601f106200030e57805160ff19168380011785556200033f565b828001600101855582156200033f579182015b828111156200033e57825182559160200191906001019062000321565b5b5090506200034e919062000352565b5090565b5b808211156200036d57600081600090555060010162000353565b5090565b6000620003886200038284620004f4565b620004cb565b905082815260208101848484011115620003a157600080fd5b620003ae8482856200056f565b509392505050565b600081519050620003c781620006a9565b92915050565b600082601f830112620003df57600080fd5b8151620003f184826020860162000371565b91505092915050565b6000806000606084860312156200041057600080fd5b600084015167ffffffffffffffff8111156200042b57600080fd5b6200043986828701620003cd565b935050602084015167ffffffffffffffff8111156200045757600080fd5b6200046586828701620003cd565b92505060406200047886828701620003b6565b9150509250925092565b600062000491601c836200052a565b91506200049e8262000680565b602082019050919050565b60006020820190508181036000830152620004c48162000482565b9050919050565b6000620004d7620004ea565b9050620004e58282620005db565b919050565b6000604051905090565b600067ffffffffffffffff82111562000512576200051162000640565b5b6200051d826200066f565b9050602081019050919050565b600082825260208201905092915050565b600062000548826200054f565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60005b838110156200058f57808201518184015260208101905062000572565b838111156200059f576000848401525b50505050565b60006002820490506001821680620005be57607f821691505b60208210811415620005d557620005d462000611565b5b50919050565b620005e6826200066f565b810181811067ffffffffffffffff8211171562000608576200060762000640565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f4552433136353a20696e76616c696420696e7465726661636520696400000000600082015250565b620006b4816200053b565b8114620006c057600080fd5b50565b61376380620006d36000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c806370a08231116100f9578063a22cb46511610097578063ca3c5c0711610071578063ca3c5c0714610513578063e985e9c51461052f578063f2fde38b1461055f578063fe575a871461057b576101c4565b8063a22cb465146104ab578063b88d4fde146104c7578063c87b56dd146104e3576101c4565b80638777a38e116100d35780638777a38e146104235780638da5cb5b1461043f578063947aea3b1461045d57806395d89b411461048d576101c4565b806370a08231146103cd578063715018a6146103fd57806373f8c0e814610407576101c4565b80632f745c59116101665780634f6ccce7116101405780634f6ccce7146103355780636352211e14610365578063644f943714610395578063667b7062146103b1576101c4565b80632f745c59146102b95780633701e582146102e957806342842e0e14610319576101c4565b8063095ea7b3116101a2578063095ea7b31461024757806318160ddd1461026357806323b872dd1461028157806329759ae91461029d576101c4565b806301ffc9a7146101c957806306fdde03146101f9578063081812fc14610217575b600080fd5b6101e360048036038101906101de91906126da565b6105ab565b6040516101f09190612c39565b60405180910390f35b610201610622565b60405161020e9190612c54565b60405180910390f35b610231600480360381019061022c9190612744565b6106b4565b60405161023e9190612bb1565b60405180910390f35b610261600480360381019061025c9190612675565b610768565b005b61026b6107a3565b6040516102789190612e96565b60405180910390f35b61029b60048036038101906102969190612517565b610894565b005b6102b760048036038101906102b29190612675565b6108cf565b005b6102d360048036038101906102ce9190612675565b6109ec565b6040516102e09190612e96565b60405180910390f35b61030360048036038101906102fe9190612489565b610a91565b6040516103109190612c17565b60405180910390f35b610333600480360381019061032e9190612517565b610ae1565b005b61034f600480360381019061034a9190612744565b610b01565b60405161035c9190612e96565b60405180910390f35b61037f600480360381019061037a9190612744565b610bb5565b60405161038c9190612bb1565b60405180910390f35b6103af60048036038101906103aa9190612489565b610c69565b005b6103cb60048036038101906103c69190612796565b610d43565b005b6103e760048036038101906103e29190612489565b610e68565b6040516103f49190612e96565b60405180910390f35b610405610f27565b005b610421600480360381019061041c9190612517565b610f3b565b005b61043d600480360381019061043891906125e1565b611371565b005b610447611464565b6040516104549190612bb1565b60405180910390f35b61047760048036038101906104729190612744565b61148e565b6040516104849190612bf5565b60405180910390f35b6104956114b2565b6040516104a29190612c54565b60405180910390f35b6104c560048036038101906104c09190612639565b611544565b005b6104e160048036038101906104dc9190612566565b61157f565b005b6104fd60048036038101906104f89190612744565b6115ba565b60405161050a9190612c54565b60405180910390f35b61052d60048036038101906105289190612744565b611673565b005b610549600480360381019061054491906124db565b6117a7565b6040516105569190612c39565b60405180910390f35b61057960048036038101906105749190612489565b61185e565b005b61059560048036038101906105909190612489565b6118e2565b6040516105a29190612c39565b60405180910390f35b60006105b682611938565b8061061b5750600080837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff165b9050919050565b60606005805461063190613106565b80601f016020809104026020016040519081016040528092919081815260200182805461065d90613106565b80156106aa5780601f1061067f576101008083540402835291602001916106aa565b820191906000526020600020905b81548152906001019060200180831161068d57829003601f168201915b5050505050905090565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663081812fc836040518263ffffffff1660e01b81526004016107119190612e96565b60206040518083038186803b15801561072957600080fd5b505afa15801561073d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076191906124b2565b9050919050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079a90612cf6565b60405180910390fd5b600080600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561080e57600080fd5b505afa158015610822573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610846919061276d565b90506000600190505b81811161088f57610871600360008381526020019081526020016000206119a2565b8361087c9190612fc6565b92508061088890613169565b905061084f565b505090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c690612db6565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061090f575061090e33826119b7565b5b61094e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161094590612cb6565b60405180910390fd5b61099f81600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611c3390919063ffffffff16565b6109de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109d590612d16565b60405180910390fd5b6109e88282611c4d565b5050565b60006109f783610e68565b8210610a38576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a2f90612e16565b60405180910390fd5b610a8982600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d6a90919063ffffffff16565b905092915050565b6060610ada600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d84565b9050919050565b610afc8383836040518060200160405280600081525061157f565b505050565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634f6ccce7836040518263ffffffff1660e01b8152600401610b5e9190612e96565b60206040518083038186803b158015610b7657600080fd5b505afa158015610b8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bae919061276d565b9050919050565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401610c129190612e96565b60206040518083038186803b158015610c2a57600080fd5b505afa158015610c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6291906124b2565b9050919050565b8073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610ca95750610ca881336117a7565b5b610ce8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cdf90612dd6565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610da55750610da433846119b7565b5b610de4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ddb90612c76565b60405180910390fd5b60005b82829050811015610e62576000838383818110610e2d577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9050602002016020810190610e429190612489565b9050610e4e8186611c4d565b508080610e5a90613169565b915050610de7565b50505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ed9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed090612d36565b60405180910390fd5b610f20600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611da5565b9050919050565b610f2f611dba565b610f396000611e38565b565b610f4533826119b7565b610f84576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f7b90612cb6565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401610ff69190612e96565b60206040518083038186803b15801561100e57600080fd5b505afa158015611022573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104691906124b2565b73ffffffffffffffffffffffffffffffffffffffff161461109c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109390612e36565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561110c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161110390612d76565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561117b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161117290612d56565b60405180910390fd5b600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611208576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ff90612e56565b60405180910390fd5b61125981600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611c3390919063ffffffff16565b15611299576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129090612cd6565b60405180910390fd5b6112ea81600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611efe90919063ffffffff16565b506113108260036000848152602001908152602001600020611f1890919063ffffffff16565b50808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806113b157506113b083336117a7565b5b6113f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e790612e76565b60405180910390fd5b60005b8282905081101561145e576000838383818110611439577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020135905061144c8582611c4d565b508061145790613169565b90506113f3565b50505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606114ab60036000848152602001908152602001600020611f48565b9050919050565b6060600680546114c190613106565b80601f01602080910402602001604051908101604052809291908181526020018280546114ed90613106565b801561153a5780601f1061150f5761010080835404028352916020019161153a565b820191906000526020600020905b81548152906001019060200180831161151d57829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161157690612cf6565b60405180910390fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115b190612db6565b60405180910390fd5b6060600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c87b56dd836040518263ffffffff1660e01b81526004016116179190612e96565b60006040518083038186803b15801561162f57600080fd5b505afa158015611643573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061166c9190612703565b9050919050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806116d557506116d433826119b7565b5b611714576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161170b90612c76565b60405180910390fd5b600061173160036000848152602001908152602001600020611f48565b905060005b81518110156117a257600082828151811061177a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020026020010151905061178e8185611c4d565b50808061179a90613169565b915050611736565b505050565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e985e9c584846040518363ffffffff1660e01b8152600401611806929190612bcc565b60206040518083038186803b15801561181e57600080fd5b505afa158015611832573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185691906126b1565b905092915050565b611866611dba565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156118d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118cd90612c96565b60405180910390fd5b6118df81611e38565b50565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60006119b082600001611f69565b9050919050565b600080600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b8152600401611a159190612e96565b60206040518083038186803b158015611a2d57600080fd5b505afa158015611a41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6591906124b2565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611b7657508373ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663081812fc856040518263ffffffff1660e01b8152600401611b0e9190612e96565b60206040518083038186803b158015611b2657600080fd5b505afa158015611b3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5e91906124b2565b73ffffffffffffffffffffffffffffffffffffffff16145b80611c2a5750600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e985e9c582866040518363ffffffff1660e01b8152600401611bd9929190612bcc565b60206040518083038186803b158015611bf157600080fd5b505afa158015611c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2991906126b1565b5b91505092915050565b6000611c45836000018360001b611f7a565b905092915050565b611c9e81600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611f9d90919063ffffffff16565b8015611ccb5750611cca8260036000848152602001908152602001600020611fb790919063ffffffff16565b5b611d0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d0190612df6565b60405180910390fd5b80600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b6000611d798360000183611fe7565b60001c905092915050565b60606000611d9483600001612038565b905060608190508092505050919050565b6000611db382600001611f69565b9050919050565b611dc2612094565b73ffffffffffffffffffffffffffffffffffffffff16611de0611464565b73ffffffffffffffffffffffffffffffffffffffff1614611e36576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e2d90612d96565b60405180910390fd5b565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000611f10836000018360001b61209c565b905092915050565b6000611f40836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61209c565b905092915050565b60606000611f5883600001612038565b905060608190508092505050919050565b600081600001805490509050919050565b600080836001016000848152602001908152602001600020541415905092915050565b6000611faf836000018360001b61210c565b905092915050565b6000611fdf836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61210c565b905092915050565b6000826000018281548110612025577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905092915050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561208857602002820191906000526020600020905b815481526020019060010190808311612074575b50505050509050919050565b600033905090565b60006120a88383611f7a565b612101578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050612106565b600090505b92915050565b6000808360010160008481526020019081526020016000205490506000811461228657600060018261213e919061301c565b9050600060018660000180549050612156919061301c565b905081811461221157600086600001828154811061219d577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001549050808760000184815481106121e7577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b8560000180548061224b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061228c565b60009150505b92915050565b60006122a56122a084612ed6565b612eb1565b9050828152602081018484840111156122bd57600080fd5b6122c88482856130c4565b509392505050565b60006122e36122de84612f07565b612eb1565b9050828152602081018484840111156122fb57600080fd5b6123068482856130d3565b509392505050565b60008135905061231d816136d1565b92915050565b600081519050612332816136d1565b92915050565b60008083601f84011261234a57600080fd5b8235905067ffffffffffffffff81111561236357600080fd5b60208301915083602082028301111561237b57600080fd5b9250929050565b60008083601f84011261239457600080fd5b8235905067ffffffffffffffff8111156123ad57600080fd5b6020830191508360208202830111156123c557600080fd5b9250929050565b6000813590506123db816136e8565b92915050565b6000815190506123f0816136e8565b92915050565b600081359050612405816136ff565b92915050565b600082601f83011261241c57600080fd5b813561242c848260208601612292565b91505092915050565b600082601f83011261244657600080fd5b81516124568482602086016122d0565b91505092915050565b60008135905061246e81613716565b92915050565b60008151905061248381613716565b92915050565b60006020828403121561249b57600080fd5b60006124a98482850161230e565b91505092915050565b6000602082840312156124c457600080fd5b60006124d284828501612323565b91505092915050565b600080604083850312156124ee57600080fd5b60006124fc8582860161230e565b925050602061250d8582860161230e565b9150509250929050565b60008060006060848603121561252c57600080fd5b600061253a8682870161230e565b935050602061254b8682870161230e565b925050604061255c8682870161245f565b9150509250925092565b6000806000806080858703121561257c57600080fd5b600061258a8782880161230e565b945050602061259b8782880161230e565b93505060406125ac8782880161245f565b925050606085013567ffffffffffffffff8111156125c957600080fd5b6125d58782880161240b565b91505092959194509250565b6000806000604084860312156125f657600080fd5b60006126048682870161230e565b935050602084013567ffffffffffffffff81111561262157600080fd5b61262d86828701612382565b92509250509250925092565b6000806040838503121561264c57600080fd5b600061265a8582860161230e565b925050602061266b858286016123cc565b9150509250929050565b6000806040838503121561268857600080fd5b60006126968582860161230e565b92505060206126a78582860161245f565b9150509250929050565b6000602082840312156126c357600080fd5b60006126d1848285016123e1565b91505092915050565b6000602082840312156126ec57600080fd5b60006126fa848285016123f6565b91505092915050565b60006020828403121561271557600080fd5b600082015167ffffffffffffffff81111561272f57600080fd5b61273b84828501612435565b91505092915050565b60006020828403121561275657600080fd5b60006127648482850161245f565b91505092915050565b60006020828403121561277f57600080fd5b600061278d84828501612474565b91505092915050565b6000806000604084860312156127ab57600080fd5b60006127b98682870161245f565b935050602084013567ffffffffffffffff8111156127d657600080fd5b6127e286828701612338565b92509250509250925092565b60006127fa838361281e565b60208301905092915050565b60006128128383612b93565b60208301905092915050565b61282781613050565b82525050565b61283681613050565b82525050565b600061284782612f58565b6128518185612f93565b935061285c83612f38565b8060005b8381101561288d57815161287488826127ee565b975061287f83612f79565b925050600181019050612860565b5085935050505092915050565b60006128a582612f63565b6128af8185612fa4565b93506128ba83612f48565b8060005b838110156128eb5781516128d28882612806565b97506128dd83612f86565b9250506001810190506128be565b5085935050505092915050565b61290181613062565b82525050565b600061291282612f6e565b61291c8185612fb5565b935061292c8185602086016130d3565b6129358161323f565b840191505092915050565b600061294d603a83612fb5565b915061295882613250565b604082019050919050565b6000612970602683612fb5565b915061297b8261329f565b604082019050919050565b6000612993602783612fb5565b915061299e826132ee565b604082019050919050565b60006129b6603383612fb5565b91506129c18261333d565b604082019050919050565b60006129d9602583612fb5565b91506129e48261338c565b604082019050919050565b60006129fc602383612fb5565b9150612a07826133db565b604082019050919050565b6000612a1f602a83612fb5565b9150612a2a8261342a565b604082019050919050565b6000612a42601783612fb5565b9150612a4d82613479565b602082019050919050565b6000612a65601e83612fb5565b9150612a70826134a2565b602082019050919050565b6000612a88602083612fb5565b9150612a93826134cb565b602082019050919050565b6000612aab602683612fb5565b9150612ab6826134f4565b604082019050919050565b6000612ace602f83612fb5565b9150612ad982613543565b604082019050919050565b6000612af1601b83612fb5565b9150612afc82613592565b602082019050919050565b6000612b14601383612fb5565b9150612b1f826135bb565b602082019050919050565b6000612b37602383612fb5565b9150612b42826135e4565b604082019050919050565b6000612b5a602683612fb5565b9150612b6582613633565b604082019050919050565b6000612b7d603283612fb5565b9150612b8882613682565b604082019050919050565b612b9c816130ba565b82525050565b612bab816130ba565b82525050565b6000602082019050612bc6600083018461282d565b92915050565b6000604082019050612be1600083018561282d565b612bee602083018461282d565b9392505050565b60006020820190508181036000830152612c0f818461283c565b905092915050565b60006020820190508181036000830152612c31818461289a565b905092915050565b6000602082019050612c4e60008301846128f8565b92915050565b60006020820190508181036000830152612c6e8184612907565b905092915050565b60006020820190508181036000830152612c8f81612940565b9050919050565b60006020820190508181036000830152612caf81612963565b9050919050565b60006020820190508181036000830152612ccf81612986565b9050919050565b60006020820190508181036000830152612cef816129a9565b9050919050565b60006020820190508181036000830152612d0f816129cc565b9050919050565b60006020820190508181036000830152612d2f816129ef565b9050919050565b60006020820190508181036000830152612d4f81612a12565b9050919050565b60006020820190508181036000830152612d6f81612a35565b9050919050565b60006020820190508181036000830152612d8f81612a58565b9050919050565b60006020820190508181036000830152612daf81612a7b565b9050919050565b60006020820190508181036000830152612dcf81612a9e565b9050919050565b60006020820190508181036000830152612def81612ac1565b9050919050565b60006020820190508181036000830152612e0f81612ae4565b9050919050565b60006020820190508181036000830152612e2f81612b07565b9050919050565b60006020820190508181036000830152612e4f81612b2a565b9050919050565b60006020820190508181036000830152612e6f81612b4d565b9050919050565b60006020820190508181036000830152612e8f81612b70565b9050919050565b6000602082019050612eab6000830184612ba2565b92915050565b6000612ebb612ecc565b9050612ec78282613138565b919050565b6000604051905090565b600067ffffffffffffffff821115612ef157612ef0613210565b5b612efa8261323f565b9050602081019050919050565b600067ffffffffffffffff821115612f2257612f21613210565b5b612f2b8261323f565b9050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b6000612fd1826130ba565b9150612fdc836130ba565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613011576130106131b2565b5b828201905092915050565b6000613027826130ba565b9150613032836130ba565b925082821015613045576130446131b2565b5b828203905092915050565b600061305b8261309a565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b838110156130f15780820151818401526020810190506130d6565b83811115613100576000848401525b50505050565b6000600282049050600182168061311e57607f821691505b60208210811415613132576131316131e1565b5b50919050565b6131418261323f565b810181811067ffffffffffffffff821117156131605761315f613210565b5b80604052505050565b6000613174826130ba565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156131a7576131a66131b2565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f53434152443a2063616c6c6572206973206e6f7420424341524420636f6e747260008201527f616374206e6f72206f776e6572206e6f7220617070726f766564000000000000602082015250565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a2063616c6c6572206973206e6f74206f776e6572206e6f72206160008201527f7070726f76656400000000000000000000000000000000000000000000000000602082015250565b7f53434152443a2072656365697665722077617320616c72656164792073656e7460008201527f2074686520536f756c626f756e64204361726400000000000000000000000000602082015250565b7f53434152443a2063616e6e6f7420617070726f766520536f756c626f756e642060008201527f4361726473000000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a20746f6b656e206e6f7420696e2072656365697665722773206c60008201527f6973740000000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b7f53434152443a2073656e64696e6720746f206f776e6572000000000000000000600082015250565b7f53434152443a2073656e64696e6720746f207a65726f20616464726573730000600082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b7f53434152443a2063616e6e6f74207472616e7366657220536f756c626f756e6460008201527f2043617264730000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a2063616c6c6572206973206e6f74206f776e6572206e6f72206160008201527f7070726f76656420666f7220616c6c0000000000000000000000000000000000602082015250565b7f53434152443a20746f6b656e206e6f74206f6e20746865207365740000000000600082015250565b7f496e646578206f7574206f6620626f756e647300000000000000000000000000600082015250565b7f53434152443a2073656e64696e6720636172642074686174206973206e6f742060008201527f6f776e0000000000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a20726563656976657220626c61636b6c6973746564207468656d60008201527f73656c7665730000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a2063616c6c6572206973206e6f74207265636569766572206e6f60008201527f7220617070726f76656420666f7220616c6c0000000000000000000000000000602082015250565b6136da81613050565b81146136e557600080fd5b50565b6136f181613062565b81146136fc57600080fd5b50565b6137088161306e565b811461371357600080fd5b50565b61371f816130ba565b811461372a57600080fd5b5056fea264697066735822122031628b23795ebcc7aee1a200d8f4a4c3f997784b255f55f068073ba235c5f14a64736f6c63430008040033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000384c8072da488698df87c02cdf04499262d4697f000000000000000000000000000000000000000000000000000000000000000e536f756c626f756e64204361726400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055343415244000000000000000000000000000000000000000000000000000000
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000384c8072da488698df87c02cdf04499262d4697f000000000000000000000000000000000000000000000000000000000000000e536f756c626f756e64204361726400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055343415244000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : name_ (string): Soulbound Card
Arg [1] : symbol_ (string): SCARD
Arg [2] : _bCard (address): 0x384c8072da488698df87c02cdf04499262d4697f
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 000000000000000000000000384c8072da488698df87c02cdf04499262d4697f
Arg [3] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [4] : 536f756c626f756e642043617264000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [6] : 5343415244000000000000000000000000000000000000000000000000000000
Deployed ByteCode Sourcemap
350:13923:15:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;596:188:5;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3278:100:15;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11555:137;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11238:161;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;9447:244;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;12846:179;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4584:393;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;9858:234;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;10498:149;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;13096:151;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;10789:135;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;8775:131;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7854:264;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;5746:524;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;9047:226;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1824:101:13;;;:::i;:::-;;3698:787:15;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;7157:519;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1194:85:13;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;10245:147:15;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3447:104;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;12016:169;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;13577:209;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;8500:131;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6391:570;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;12352:168;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2074:198:13;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;8232:146:15;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;596:188:5;681:4;704:36;728:11;704:23;:36::i;:::-;:73;;;;744:20;:33;765:11;744:33;;;;;;;;;;;;;;;;;;;;;;;;;;;704:73;697:80;;596:188;;;:::o;3278:100:15:-;3332:13;3365:5;3358:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3278:100;:::o;11555:137::-;11631:7;11658:5;;;;;;;;;;;:17;;;11676:7;11658:26;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11651:33;;11555:137;;;:::o;11238:161::-;11344:47;;;;;;;;;;:::i;:::-;;;;;;;;9447:244;9508:13;9534:15;9552:5;;;;;;;;;;;:17;;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9534:37;;9587:9;9599:1;9587:13;;9582:102;9607:7;9602:1;:12;9582:102;;9645:27;:15;:18;9661:1;9645:18;;;;;;;;;;;:25;:27::i;:::-;9636:36;;;;;:::i;:::-;;;9616:3;;;;:::i;:::-;;;9582:102;;;;9447:244;;:::o;12846:179::-;12969:48;;;;;;;;;;:::i;:::-;;;;;;;;4584:393;4701:8;4687:22;;:10;:22;;;:64;;;;4713:38;4732:10;4744:6;4713:18;:38::i;:::-;4687:64;4665:156;;;;;;;;;;;;:::i;:::-;;;;;;;;;4840:42;4875:6;4840:15;:25;4856:8;4840:25;;;;;;;;;;;;;;;:34;;:42;;;;:::i;:::-;4832:90;;;;;;;;;;;;:::i;:::-;;;;;;;;;4933:36;4952:8;4962:6;4933:18;:36::i;:::-;4584:393;;:::o;9858:234::-;9956:7;9992:17;10002:6;9992:9;:17::i;:::-;9984:5;:25;9976:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;10051:33;10078:5;10051:15;:23;10067:6;10051:23;;;;;;;;;;;;;;;:26;;:33;;;;:::i;:::-;10044:40;;9858:234;;;;:::o;10498:149::-;10569:16;10605:34;:15;:25;10621:8;10605:25;;;;;;;;;;;;;;;:32;:34::i;:::-;10598:41;;10498:149;;;:::o;13096:151::-;13200:39;13217:4;13223:2;13227:7;13200:39;;;;;;;;;;;;:16;:39::i;:::-;13096:151;;;:::o;10789:135::-;10864:7;10891:5;;;;;;;;;;;:18;;;10910:5;10891:25;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;10884:32;;10789:135;;;:::o;8775:131::-;8848:7;8875:5;;;;;;;;;;;:13;;;8889:8;8875:23;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8868:30;;8775:131;;;:::o;7854:264::-;7956:9;7942:23;;:10;:23;;;:66;;;;7969:39;7986:9;7997:10;7969:16;:39::i;:::-;7942:66;7934:126;;;;;;;;;;;;:::i;:::-;;;;;;;;;8106:4;8071:21;:32;8093:9;8071:32;;;;;;;;;;;;;;;;:39;;;;;;;;;;;;;;;;;;7854:264;:::o;5746:524::-;5890:5;;;;;;;;;;;5868:28;;:10;:28;;;:71;;;;5900:39;5919:10;5931:7;5900:18;:39::i;:::-;5868:71;5846:182;;;;;;;;;;;;:::i;:::-;;;;;;;;;6117:9;6112:151;6136:6;;:13;;6132:1;:17;6112:151;;;6171:16;6190:6;;6197:1;6190:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6171:28;;6214:37;6233:8;6243:7;6214:18;:37::i;:::-;6112:151;6151:3;;;;;:::i;:::-;;;;6112:151;;;;5746:524;;;:::o;9047:226::-;9120:7;9166:1;9148:20;;:6;:20;;;;9140:75;;;;;;;;;;;;:::i;:::-;;;;;;;;;9233:32;:15;:23;9249:6;9233:23;;;;;;;;;;;;;;;:30;:32::i;:::-;9226:39;;9047:226;;;:::o;1824:101:13:-;1087:13;:11;:13::i;:::-;1888:30:::1;1915:1;1888:18;:30::i;:::-;1824:101::o:0;3698:787:15:-;3802:39;3821:10;3833:7;3802:18;:39::i;:::-;3794:91;;;;;;;;;;;;:::i;:::-;;;;;;;;;3930:4;3904:30;;:5;;;;;;;;;;;:13;;;3918:7;3904:22;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:30;;;3896:78;;;;;;;;;;;;:::i;:::-;;;;;;;;;4013:1;3993:22;;:8;:22;;;;3985:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;4081:4;4069:16;;:8;:16;;;;4061:52;;;;;;;;;;;;:::i;:::-;;;;;;;;;4133:21;:31;4155:8;4133:31;;;;;;;;;;;;;;;;;;;;;;;;;4132:32;4124:83;;;;;;;;;;;;:::i;:::-;;;;;;;;;4227:43;4262:7;4227:15;:25;4243:8;4227:25;;;;;;;;;;;;;;;:34;;:43;;;;:::i;:::-;4226:44;4218:108;;;;;;;;;;;;:::i;:::-;;;;;;;;;4339:38;4369:7;4339:15;:25;4355:8;4339:25;;;;;;;;;;;;;;;:29;;:38;;;;:::i;:::-;;4388;4417:8;4388:15;:24;4404:7;4388:24;;;;;;;;;;;:28;;:38;;;;:::i;:::-;;4469:7;4459:8;4444:33;;4453:4;4444:33;;;;;;;;;;;;3698:787;;;:::o;7157:519::-;7294:8;7280:22;;:10;:22;;;:64;;;;7306:38;7323:8;7333:10;7306:16;:38::i;:::-;7280:64;7258:179;;;;;;;;;;;;:::i;:::-;;;;;;;;;7526:9;7521:148;7545:6;;:13;;7541:1;:17;7521:148;;;7580:14;7597:6;;7604:1;7597:9;;;;;;;;;;;;;;;;;;;;;7580:26;;7621:36;7640:8;7650:6;7621:18;:36::i;:::-;7521:148;7560:3;;;;:::i;:::-;;;7521:148;;;;7157:519;;;:::o;1194:85:13:-;1240:7;1266:6;;;;;;;;;;;1259:13;;1194:85;:::o;10245:147:15:-;10315:16;10351:33;:15;:24;10367:7;10351:24;;;;;;;;;;;:31;:33::i;:::-;10344:40;;10245:147;;;:::o;3447:104::-;3503:13;3536:7;3529:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3447:104;:::o;12016:169::-;12130:47;;;;;;;;;;:::i;:::-;;;;;;;;13577:209;13730:48;;;;;;;;;;:::i;:::-;;;;;;;;8500:131;8567:13;8600:5;;;;;;;;;;;:14;;;8615:7;8600:23;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8593:30;;8500:131;;;:::o;6391:570::-;6511:5;;;;;;;;;;;6489:28;;:10;:28;;;:71;;;;6521:39;6540:10;6552:7;6521:18;:39::i;:::-;6489:71;6467:182;;;;;;;;;;;;:::i;:::-;;;;;;;;;6733:23;6759:33;:15;:24;6775:7;6759:24;;;;;;;;;;;:31;:33::i;:::-;6733:59;;6808:9;6803:151;6827:6;:13;6823:1;:17;6803:151;;;6862:16;6881:6;6888:1;6881:9;;;;;;;;;;;;;;;;;;;;;;6862:28;;6905:37;6924:8;6934:7;6905:18;:37::i;:::-;6803:151;6842:3;;;;;:::i;:::-;;;;6803:151;;;;6391:570;;:::o;12352:168::-;12449:4;12473:5;;;;;;;;;;;:22;;;12496:5;12503:8;12473:39;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12466:46;;12352:168;;;;:::o;2074:198:13:-;1087:13;:11;:13::i;:::-;2182:1:::1;2162:22;;:8;:22;;;;2154:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;2237:28;2256:8;2237:18;:28::i;:::-;2074:198:::0;:::o;8232:146:15:-;8296:16;8339:21;:31;8361:8;8339:31;;;;;;;;;;;;;;;;;;;;;;;;;8325:45;;8232:146;;;:::o;829:155:4:-;914:4;952:25;937:40;;;:11;:40;;;;930:47;;829:155;;;:::o;8829:115:7:-;8892:7;8918:19;8926:3;:10;;8918:7;:19::i;:::-;8911:26;;8829:115;;;:::o;13989:275:15:-;14082:4;14099:13;14115:5;;;;;;;;;;;:13;;;14129:7;14115:22;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14099:38;;14167:5;14156:16;;:7;:16;;;:57;;;;14206:7;14176:37;;:5;;;;;;;;;;;:17;;;14194:7;14176:26;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:37;;;14156:57;:99;;;;14217:5;;;;;;;;;;;:22;;;14240:5;14247:7;14217:38;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14156:99;14148:108;;;13989:275;;;;:::o;11029:144:7:-;11106:4;11129:37;11139:3;:10;;11159:5;11151:14;;11129:9;:37::i;:::-;11122:44;;11029:144;;;;:::o;5076:553:15:-;5273:40;5306:6;5273:15;:25;5289:8;5273:25;;;;;;;;;;;;;;;:32;;:40;;;;:::i;:::-;:215;;;;;5448:40;5479:8;5448:15;:23;5464:6;5448:23;;;;;;;;;;;:30;;:40;;;;:::i;:::-;5273:215;5158:399;;;;;;;;;;;;:::i;:::-;;;;;;;;;5614:6;5610:1;5583:38;;5592:8;5583:38;;;;;;;;;;;;5076:553;;:::o;11708:135:7:-;11779:7;11813:22;11817:3;:10;;11829:5;11813:3;:22::i;:::-;11805:31;;11798:38;;11708:135;;;;:::o;12383:297::-;12443:16;12471:22;12496:19;12504:3;:10;;12496:7;:19::i;:::-;12471:44;;12525:23;12635:5;12625:15;;12667:6;12660:13;;;;12383:297;;;:::o;11254:112::-;11314:7;11340:19;11348:3;:10;;11340:7;:19::i;:::-;11333:26;;11254:112;;;:::o;1352:130:13:-;1426:12;:10;:12::i;:::-;1415:23;;:7;:5;:7::i;:::-;:23;;;1407:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;1352:130::o;2426:187::-;2499:16;2518:6;;;;;;;;;;;2499:25;;2543:8;2534:6;;:17;;;;;;;;;;;;;;;;;;2597:8;2566:40;;2587:8;2566:40;;;;;;;;;;;;2426:187;;:::o;10516:129:7:-;10583:4;10606:32;10611:3;:10;;10631:5;10623:14;;10606:4;:32::i;:::-;10599:39;;10516:129;;;;:::o;8028:150::-;8098:4;8121:50;8126:3;:10;;8162:5;8146:23;;8138:32;;8121:4;:50::i;:::-;8114:57;;8028:150;;;;:::o;9982:300::-;10045:16;10073:22;10098:19;10106:3;:10;;10098:7;:19::i;:::-;10073:44;;10127:23;10237:5;10227:15;;10269:6;10262:13;;;;9982:300;;;:::o;4362:107::-;4418:7;4444:3;:11;;:18;;;;4437:25;;4362:107;;;:::o;4154:127::-;4227:4;4273:1;4250:3;:12;;:19;4263:5;4250:19;;;;;;;;;;;;:24;;4243:31;;4154:127;;;;:::o;10813:135::-;10883:4;10906:35;10914:3;:10;;10934:5;10926:14;;10906:7;:35::i;:::-;10899:42;;10813:135;;;;:::o;8346:156::-;8419:4;8442:53;8450:3;:10;;8486:5;8470:23;;8462:32;;8442:7;:53::i;:::-;8435:60;;8346:156;;;;:::o;4811:118::-;4878:7;4904:3;:11;;4916:5;4904:18;;;;;;;;;;;;;;;;;;;;;;;;4897:25;;4811:118;;;;:::o;5469:109::-;5525:16;5560:3;:11;;5553:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5469:109;;;:::o;640:96:3:-;693:7;719:10;712:17;;640:96;:::o;2113:404:7:-;2176:4;2197:21;2207:3;2212:5;2197:9;:21::i;:::-;2192:319;;2234:3;:11;;2251:5;2234:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2414:3;:11;;:18;;;;2392:3;:12;;:19;2405:5;2392:19;;;;;;;;;;;:40;;;;2453:4;2446:11;;;;2192:319;2495:5;2488:12;;2113:404;;;;;:::o;2685:1388::-;2751:4;2867:18;2888:3;:12;;:19;2901:5;2888:19;;;;;;;;;;;;2867:40;;2936:1;2922:10;:15;2918:1149;;3291:21;3328:1;3315:10;:14;;;;:::i;:::-;3291:38;;3343:17;3384:1;3363:3;:11;;:18;;;;:22;;;;:::i;:::-;3343:42;;3417:13;3404:9;:26;3400:398;;3450:17;3470:3;:11;;3482:9;3470:22;;;;;;;;;;;;;;;;;;;;;;;;3450:42;;3621:9;3592:3;:11;;3604:13;3592:26;;;;;;;;;;;;;;;;;;;;;;;:38;;;;3730:10;3704:3;:12;;:23;3717:9;3704:23;;;;;;;;;;;:36;;;;3400:398;;3876:3;:11;;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3968:3;:12;;:19;3981:5;3968:19;;;;;;;;;;;3961:26;;;4009:4;4002:11;;;;;;;2918:1149;4051:5;4044:12;;;2685:1388;;;;;:::o;7:343:17:-;84:5;109:65;125:48;166:6;125:48;:::i;:::-;109:65;:::i;:::-;100:74;;197:6;190:5;183:21;235:4;228:5;224:16;273:3;264:6;259:3;255:16;252:25;249:2;;;290:1;287;280:12;249:2;303:41;337:6;332:3;327;303:41;:::i;:::-;90:260;;;;;;:::o;356:354::-;445:5;470:66;486:49;528:6;486:49;:::i;:::-;470:66;:::i;:::-;461:75;;559:6;552:5;545:21;597:4;590:5;586:16;635:3;626:6;621:3;617:16;614:25;611:2;;;652:1;649;642:12;611:2;665:39;697:6;692:3;687;665:39;:::i;:::-;451:259;;;;;;:::o;716:139::-;762:5;800:6;787:20;778:29;;816:33;843:5;816:33;:::i;:::-;768:87;;;;:::o;861:143::-;918:5;949:6;943:13;934:22;;965:33;992:5;965:33;:::i;:::-;924:80;;;;:::o;1027:367::-;1100:8;1110:6;1160:3;1153:4;1145:6;1141:17;1137:27;1127:2;;1178:1;1175;1168:12;1127:2;1214:6;1201:20;1191:30;;1244:18;1236:6;1233:30;1230:2;;;1276:1;1273;1266:12;1230:2;1313:4;1305:6;1301:17;1289:29;;1367:3;1359:4;1351:6;1347:17;1337:8;1333:32;1330:41;1327:2;;;1384:1;1381;1374:12;1327:2;1117:277;;;;;:::o;1417:367::-;1490:8;1500:6;1550:3;1543:4;1535:6;1531:17;1527:27;1517:2;;1568:1;1565;1558:12;1517:2;1604:6;1591:20;1581:30;;1634:18;1626:6;1623:30;1620:2;;;1666:1;1663;1656:12;1620:2;1703:4;1695:6;1691:17;1679:29;;1757:3;1749:4;1741:6;1737:17;1727:8;1723:32;1720:41;1717:2;;;1774:1;1771;1764:12;1717:2;1507:277;;;;;:::o;1790:133::-;1833:5;1871:6;1858:20;1849:29;;1887:30;1911:5;1887:30;:::i;:::-;1839:84;;;;:::o;1929:137::-;1983:5;2014:6;2008:13;1999:22;;2030:30;2054:5;2030:30;:::i;:::-;1989:77;;;;:::o;2072:137::-;2117:5;2155:6;2142:20;2133:29;;2171:32;2197:5;2171:32;:::i;:::-;2123:86;;;;:::o;2228:271::-;2283:5;2332:3;2325:4;2317:6;2313:17;2309:27;2299:2;;2350:1;2347;2340:12;2299:2;2390:6;2377:20;2415:78;2489:3;2481:6;2474:4;2466:6;2462:17;2415:78;:::i;:::-;2406:87;;2289:210;;;;;:::o;2519:288::-;2586:5;2635:3;2628:4;2620:6;2616:17;2612:27;2602:2;;2653:1;2650;2643:12;2602:2;2686:6;2680:13;2711:90;2797:3;2789:6;2782:4;2774:6;2770:17;2711:90;:::i;:::-;2702:99;;2592:215;;;;;:::o;2813:139::-;2859:5;2897:6;2884:20;2875:29;;2913:33;2940:5;2913:33;:::i;:::-;2865:87;;;;:::o;2958:143::-;3015:5;3046:6;3040:13;3031:22;;3062:33;3089:5;3062:33;:::i;:::-;3021:80;;;;:::o;3107:262::-;3166:6;3215:2;3203:9;3194:7;3190:23;3186:32;3183:2;;;3231:1;3228;3221:12;3183:2;3274:1;3299:53;3344:7;3335:6;3324:9;3320:22;3299:53;:::i;:::-;3289:63;;3245:117;3173:196;;;;:::o;3375:284::-;3445:6;3494:2;3482:9;3473:7;3469:23;3465:32;3462:2;;;3510:1;3507;3500:12;3462:2;3553:1;3578:64;3634:7;3625:6;3614:9;3610:22;3578:64;:::i;:::-;3568:74;;3524:128;3452:207;;;;:::o;3665:407::-;3733:6;3741;3790:2;3778:9;3769:7;3765:23;3761:32;3758:2;;;3806:1;3803;3796:12;3758:2;3849:1;3874:53;3919:7;3910:6;3899:9;3895:22;3874:53;:::i;:::-;3864:63;;3820:117;3976:2;4002:53;4047:7;4038:6;4027:9;4023:22;4002:53;:::i;:::-;3992:63;;3947:118;3748:324;;;;;:::o;4078:552::-;4155:6;4163;4171;4220:2;4208:9;4199:7;4195:23;4191:32;4188:2;;;4236:1;4233;4226:12;4188:2;4279:1;4304:53;4349:7;4340:6;4329:9;4325:22;4304:53;:::i;:::-;4294:63;;4250:117;4406:2;4432:53;4477:7;4468:6;4457:9;4453:22;4432:53;:::i;:::-;4422:63;;4377:118;4534:2;4560:53;4605:7;4596:6;4585:9;4581:22;4560:53;:::i;:::-;4550:63;;4505:118;4178:452;;;;;:::o;4636:809::-;4731:6;4739;4747;4755;4804:3;4792:9;4783:7;4779:23;4775:33;4772:2;;;4821:1;4818;4811:12;4772:2;4864:1;4889:53;4934:7;4925:6;4914:9;4910:22;4889:53;:::i;:::-;4879:63;;4835:117;4991:2;5017:53;5062:7;5053:6;5042:9;5038:22;5017:53;:::i;:::-;5007:63;;4962:118;5119:2;5145:53;5190:7;5181:6;5170:9;5166:22;5145:53;:::i;:::-;5135:63;;5090:118;5275:2;5264:9;5260:18;5247:32;5306:18;5298:6;5295:30;5292:2;;;5338:1;5335;5328:12;5292:2;5366:62;5420:7;5411:6;5400:9;5396:22;5366:62;:::i;:::-;5356:72;;5218:220;4762:683;;;;;;;:::o;5451:570::-;5546:6;5554;5562;5611:2;5599:9;5590:7;5586:23;5582:32;5579:2;;;5627:1;5624;5617:12;5579:2;5670:1;5695:53;5740:7;5731:6;5720:9;5716:22;5695:53;:::i;:::-;5685:63;;5641:117;5825:2;5814:9;5810:18;5797:32;5856:18;5848:6;5845:30;5842:2;;;5888:1;5885;5878:12;5842:2;5924:80;5996:7;5987:6;5976:9;5972:22;5924:80;:::i;:::-;5906:98;;;;5768:246;5569:452;;;;;:::o;6027:401::-;6092:6;6100;6149:2;6137:9;6128:7;6124:23;6120:32;6117:2;;;6165:1;6162;6155:12;6117:2;6208:1;6233:53;6278:7;6269:6;6258:9;6254:22;6233:53;:::i;:::-;6223:63;;6179:117;6335:2;6361:50;6403:7;6394:6;6383:9;6379:22;6361:50;:::i;:::-;6351:60;;6306:115;6107:321;;;;;:::o;6434:407::-;6502:6;6510;6559:2;6547:9;6538:7;6534:23;6530:32;6527:2;;;6575:1;6572;6565:12;6527:2;6618:1;6643:53;6688:7;6679:6;6668:9;6664:22;6643:53;:::i;:::-;6633:63;;6589:117;6745:2;6771:53;6816:7;6807:6;6796:9;6792:22;6771:53;:::i;:::-;6761:63;;6716:118;6517:324;;;;;:::o;6847:278::-;6914:6;6963:2;6951:9;6942:7;6938:23;6934:32;6931:2;;;6979:1;6976;6969:12;6931:2;7022:1;7047:61;7100:7;7091:6;7080:9;7076:22;7047:61;:::i;:::-;7037:71;;6993:125;6921:204;;;;:::o;7131:260::-;7189:6;7238:2;7226:9;7217:7;7213:23;7209:32;7206:2;;;7254:1;7251;7244:12;7206:2;7297:1;7322:52;7366:7;7357:6;7346:9;7342:22;7322:52;:::i;:::-;7312:62;;7268:116;7196:195;;;;:::o;7397:390::-;7477:6;7526:2;7514:9;7505:7;7501:23;7497:32;7494:2;;;7542:1;7539;7532:12;7494:2;7606:1;7595:9;7591:17;7585:24;7636:18;7628:6;7625:30;7622:2;;;7668:1;7665;7658:12;7622:2;7696:74;7762:7;7753:6;7742:9;7738:22;7696:74;:::i;:::-;7686:84;;7556:224;7484:303;;;;:::o;7793:262::-;7852:6;7901:2;7889:9;7880:7;7876:23;7872:32;7869:2;;;7917:1;7914;7907:12;7869:2;7960:1;7985:53;8030:7;8021:6;8010:9;8006:22;7985:53;:::i;:::-;7975:63;;7931:117;7859:196;;;;:::o;8061:284::-;8131:6;8180:2;8168:9;8159:7;8155:23;8151:32;8148:2;;;8196:1;8193;8186:12;8148:2;8239:1;8264:64;8320:7;8311:6;8300:9;8296:22;8264:64;:::i;:::-;8254:74;;8210:128;8138:207;;;;:::o;8351:570::-;8446:6;8454;8462;8511:2;8499:9;8490:7;8486:23;8482:32;8479:2;;;8527:1;8524;8517:12;8479:2;8570:1;8595:53;8640:7;8631:6;8620:9;8616:22;8595:53;:::i;:::-;8585:63;;8541:117;8725:2;8714:9;8710:18;8697:32;8756:18;8748:6;8745:30;8742:2;;;8788:1;8785;8778:12;8742:2;8824:80;8896:7;8887:6;8876:9;8872:22;8824:80;:::i;:::-;8806:98;;;;8668:246;8469:452;;;;;:::o;8927:179::-;8996:10;9017:46;9059:3;9051:6;9017:46;:::i;:::-;9095:4;9090:3;9086:14;9072:28;;9007:99;;;;:::o;9112:179::-;9181:10;9202:46;9244:3;9236:6;9202:46;:::i;:::-;9280:4;9275:3;9271:14;9257:28;;9192:99;;;;:::o;9297:108::-;9374:24;9392:5;9374:24;:::i;:::-;9369:3;9362:37;9352:53;;:::o;9411:118::-;9498:24;9516:5;9498:24;:::i;:::-;9493:3;9486:37;9476:53;;:::o;9565:732::-;9684:3;9713:54;9761:5;9713:54;:::i;:::-;9783:86;9862:6;9857:3;9783:86;:::i;:::-;9776:93;;9893:56;9943:5;9893:56;:::i;:::-;9972:7;10003:1;9988:284;10013:6;10010:1;10007:13;9988:284;;;10089:6;10083:13;10116:63;10175:3;10160:13;10116:63;:::i;:::-;10109:70;;10202:60;10255:6;10202:60;:::i;:::-;10192:70;;10048:224;10035:1;10032;10028:9;10023:14;;9988:284;;;9992:14;10288:3;10281:10;;9689:608;;;;;;;:::o;10333:732::-;10452:3;10481:54;10529:5;10481:54;:::i;:::-;10551:86;10630:6;10625:3;10551:86;:::i;:::-;10544:93;;10661:56;10711:5;10661:56;:::i;:::-;10740:7;10771:1;10756:284;10781:6;10778:1;10775:13;10756:284;;;10857:6;10851:13;10884:63;10943:3;10928:13;10884:63;:::i;:::-;10877:70;;10970:60;11023:6;10970:60;:::i;:::-;10960:70;;10816:224;10803:1;10800;10796:9;10791:14;;10756:284;;;10760:14;11056:3;11049:10;;10457:608;;;;;;;:::o;11071:109::-;11152:21;11167:5;11152:21;:::i;:::-;11147:3;11140:34;11130:50;;:::o;11186:364::-;11274:3;11302:39;11335:5;11302:39;:::i;:::-;11357:71;11421:6;11416:3;11357:71;:::i;:::-;11350:78;;11437:52;11482:6;11477:3;11470:4;11463:5;11459:16;11437:52;:::i;:::-;11514:29;11536:6;11514:29;:::i;:::-;11509:3;11505:39;11498:46;;11278:272;;;;;:::o;11556:366::-;11698:3;11719:67;11783:2;11778:3;11719:67;:::i;:::-;11712:74;;11795:93;11884:3;11795:93;:::i;:::-;11913:2;11908:3;11904:12;11897:19;;11702:220;;;:::o;11928:366::-;12070:3;12091:67;12155:2;12150:3;12091:67;:::i;:::-;12084:74;;12167:93;12256:3;12167:93;:::i;:::-;12285:2;12280:3;12276:12;12269:19;;12074:220;;;:::o;12300:366::-;12442:3;12463:67;12527:2;12522:3;12463:67;:::i;:::-;12456:74;;12539:93;12628:3;12539:93;:::i;:::-;12657:2;12652:3;12648:12;12641:19;;12446:220;;;:::o;12672:366::-;12814:3;12835:67;12899:2;12894:3;12835:67;:::i;:::-;12828:74;;12911:93;13000:3;12911:93;:::i;:::-;13029:2;13024:3;13020:12;13013:19;;12818:220;;;:::o;13044:366::-;13186:3;13207:67;13271:2;13266:3;13207:67;:::i;:::-;13200:74;;13283:93;13372:3;13283:93;:::i;:::-;13401:2;13396:3;13392:12;13385:19;;13190:220;;;:::o;13416:366::-;13558:3;13579:67;13643:2;13638:3;13579:67;:::i;:::-;13572:74;;13655:93;13744:3;13655:93;:::i;:::-;13773:2;13768:3;13764:12;13757:19;;13562:220;;;:::o;13788:366::-;13930:3;13951:67;14015:2;14010:3;13951:67;:::i;:::-;13944:74;;14027:93;14116:3;14027:93;:::i;:::-;14145:2;14140:3;14136:12;14129:19;;13934:220;;;:::o;14160:366::-;14302:3;14323:67;14387:2;14382:3;14323:67;:::i;:::-;14316:74;;14399:93;14488:3;14399:93;:::i;:::-;14517:2;14512:3;14508:12;14501:19;;14306:220;;;:::o;14532:366::-;14674:3;14695:67;14759:2;14754:3;14695:67;:::i;:::-;14688:74;;14771:93;14860:3;14771:93;:::i;:::-;14889:2;14884:3;14880:12;14873:19;;14678:220;;;:::o;14904:366::-;15046:3;15067:67;15131:2;15126:3;15067:67;:::i;:::-;15060:74;;15143:93;15232:3;15143:93;:::i;:::-;15261:2;15256:3;15252:12;15245:19;;15050:220;;;:::o;15276:366::-;15418:3;15439:67;15503:2;15498:3;15439:67;:::i;:::-;15432:74;;15515:93;15604:3;15515:93;:::i;:::-;15633:2;15628:3;15624:12;15617:19;;15422:220;;;:::o;15648:366::-;15790:3;15811:67;15875:2;15870:3;15811:67;:::i;:::-;15804:74;;15887:93;15976:3;15887:93;:::i;:::-;16005:2;16000:3;15996:12;15989:19;;15794:220;;;:::o;16020:366::-;16162:3;16183:67;16247:2;16242:3;16183:67;:::i;:::-;16176:74;;16259:93;16348:3;16259:93;:::i;:::-;16377:2;16372:3;16368:12;16361:19;;16166:220;;;:::o;16392:366::-;16534:3;16555:67;16619:2;16614:3;16555:67;:::i;:::-;16548:74;;16631:93;16720:3;16631:93;:::i;:::-;16749:2;16744:3;16740:12;16733:19;;16538:220;;;:::o;16764:366::-;16906:3;16927:67;16991:2;16986:3;16927:67;:::i;:::-;16920:74;;17003:93;17092:3;17003:93;:::i;:::-;17121:2;17116:3;17112:12;17105:19;;16910:220;;;:::o;17136:366::-;17278:3;17299:67;17363:2;17358:3;17299:67;:::i;:::-;17292:74;;17375:93;17464:3;17375:93;:::i;:::-;17493:2;17488:3;17484:12;17477:19;;17282:220;;;:::o;17508:366::-;17650:3;17671:67;17735:2;17730:3;17671:67;:::i;:::-;17664:74;;17747:93;17836:3;17747:93;:::i;:::-;17865:2;17860:3;17856:12;17849:19;;17654:220;;;:::o;17880:108::-;17957:24;17975:5;17957:24;:::i;:::-;17952:3;17945:37;17935:53;;:::o;17994:118::-;18081:24;18099:5;18081:24;:::i;:::-;18076:3;18069:37;18059:53;;:::o;18118:222::-;18211:4;18249:2;18238:9;18234:18;18226:26;;18262:71;18330:1;18319:9;18315:17;18306:6;18262:71;:::i;:::-;18216:124;;;;:::o;18346:332::-;18467:4;18505:2;18494:9;18490:18;18482:26;;18518:71;18586:1;18575:9;18571:17;18562:6;18518:71;:::i;:::-;18599:72;18667:2;18656:9;18652:18;18643:6;18599:72;:::i;:::-;18472:206;;;;;:::o;18684:373::-;18827:4;18865:2;18854:9;18850:18;18842:26;;18914:9;18908:4;18904:20;18900:1;18889:9;18885:17;18878:47;18942:108;19045:4;19036:6;18942:108;:::i;:::-;18934:116;;18832:225;;;;:::o;19063:373::-;19206:4;19244:2;19233:9;19229:18;19221:26;;19293:9;19287:4;19283:20;19279:1;19268:9;19264:17;19257:47;19321:108;19424:4;19415:6;19321:108;:::i;:::-;19313:116;;19211:225;;;;:::o;19442:210::-;19529:4;19567:2;19556:9;19552:18;19544:26;;19580:65;19642:1;19631:9;19627:17;19618:6;19580:65;:::i;:::-;19534:118;;;;:::o;19658:313::-;19771:4;19809:2;19798:9;19794:18;19786:26;;19858:9;19852:4;19848:20;19844:1;19833:9;19829:17;19822:47;19886:78;19959:4;19950:6;19886:78;:::i;:::-;19878:86;;19776:195;;;;:::o;19977:419::-;20143:4;20181:2;20170:9;20166:18;20158:26;;20230:9;20224:4;20220:20;20216:1;20205:9;20201:17;20194:47;20258:131;20384:4;20258:131;:::i;:::-;20250:139;;20148:248;;;:::o;20402:419::-;20568:4;20606:2;20595:9;20591:18;20583:26;;20655:9;20649:4;20645:20;20641:1;20630:9;20626:17;20619:47;20683:131;20809:4;20683:131;:::i;:::-;20675:139;;20573:248;;;:::o;20827:419::-;20993:4;21031:2;21020:9;21016:18;21008:26;;21080:9;21074:4;21070:20;21066:1;21055:9;21051:17;21044:47;21108:131;21234:4;21108:131;:::i;:::-;21100:139;;20998:248;;;:::o;21252:419::-;21418:4;21456:2;21445:9;21441:18;21433:26;;21505:9;21499:4;21495:20;21491:1;21480:9;21476:17;21469:47;21533:131;21659:4;21533:131;:::i;:::-;21525:139;;21423:248;;;:::o;21677:419::-;21843:4;21881:2;21870:9;21866:18;21858:26;;21930:9;21924:4;21920:20;21916:1;21905:9;21901:17;21894:47;21958:131;22084:4;21958:131;:::i;:::-;21950:139;;21848:248;;;:::o;22102:419::-;22268:4;22306:2;22295:9;22291:18;22283:26;;22355:9;22349:4;22345:20;22341:1;22330:9;22326:17;22319:47;22383:131;22509:4;22383:131;:::i;:::-;22375:139;;22273:248;;;:::o;22527:419::-;22693:4;22731:2;22720:9;22716:18;22708:26;;22780:9;22774:4;22770:20;22766:1;22755:9;22751:17;22744:47;22808:131;22934:4;22808:131;:::i;:::-;22800:139;;22698:248;;;:::o;22952:419::-;23118:4;23156:2;23145:9;23141:18;23133:26;;23205:9;23199:4;23195:20;23191:1;23180:9;23176:17;23169:47;23233:131;23359:4;23233:131;:::i;:::-;23225:139;;23123:248;;;:::o;23377:419::-;23543:4;23581:2;23570:9;23566:18;23558:26;;23630:9;23624:4;23620:20;23616:1;23605:9;23601:17;23594:47;23658:131;23784:4;23658:131;:::i;:::-;23650:139;;23548:248;;;:::o;23802:419::-;23968:4;24006:2;23995:9;23991:18;23983:26;;24055:9;24049:4;24045:20;24041:1;24030:9;24026:17;24019:47;24083:131;24209:4;24083:131;:::i;:::-;24075:139;;23973:248;;;:::o;24227:419::-;24393:4;24431:2;24420:9;24416:18;24408:26;;24480:9;24474:4;24470:20;24466:1;24455:9;24451:17;24444:47;24508:131;24634:4;24508:131;:::i;:::-;24500:139;;24398:248;;;:::o;24652:419::-;24818:4;24856:2;24845:9;24841:18;24833:26;;24905:9;24899:4;24895:20;24891:1;24880:9;24876:17;24869:47;24933:131;25059:4;24933:131;:::i;:::-;24925:139;;24823:248;;;:::o;25077:419::-;25243:4;25281:2;25270:9;25266:18;25258:26;;25330:9;25324:4;25320:20;25316:1;25305:9;25301:17;25294:47;25358:131;25484:4;25358:131;:::i;:::-;25350:139;;25248:248;;;:::o;25502:419::-;25668:4;25706:2;25695:9;25691:18;25683:26;;25755:9;25749:4;25745:20;25741:1;25730:9;25726:17;25719:47;25783:131;25909:4;25783:131;:::i;:::-;25775:139;;25673:248;;;:::o;25927:419::-;26093:4;26131:2;26120:9;26116:18;26108:26;;26180:9;26174:4;26170:20;26166:1;26155:9;26151:17;26144:47;26208:131;26334:4;26208:131;:::i;:::-;26200:139;;26098:248;;;:::o;26352:419::-;26518:4;26556:2;26545:9;26541:18;26533:26;;26605:9;26599:4;26595:20;26591:1;26580:9;26576:17;26569:47;26633:131;26759:4;26633:131;:::i;:::-;26625:139;;26523:248;;;:::o;26777:419::-;26943:4;26981:2;26970:9;26966:18;26958:26;;27030:9;27024:4;27020:20;27016:1;27005:9;27001:17;26994:47;27058:131;27184:4;27058:131;:::i;:::-;27050:139;;26948:248;;;:::o;27202:222::-;27295:4;27333:2;27322:9;27318:18;27310:26;;27346:71;27414:1;27403:9;27399:17;27390:6;27346:71;:::i;:::-;27300:124;;;;:::o;27430:129::-;27464:6;27491:20;;:::i;:::-;27481:30;;27520:33;27548:4;27540:6;27520:33;:::i;:::-;27471:88;;;:::o;27565:75::-;27598:6;27631:2;27625:9;27615:19;;27605:35;:::o;27646:307::-;27707:4;27797:18;27789:6;27786:30;27783:2;;;27819:18;;:::i;:::-;27783:2;27857:29;27879:6;27857:29;:::i;:::-;27849:37;;27941:4;27935;27931:15;27923:23;;27712:241;;;:::o;27959:308::-;28021:4;28111:18;28103:6;28100:30;28097:2;;;28133:18;;:::i;:::-;28097:2;28171:29;28193:6;28171:29;:::i;:::-;28163:37;;28255:4;28249;28245:15;28237:23;;28026:241;;;:::o;28273:132::-;28340:4;28363:3;28355:11;;28393:4;28388:3;28384:14;28376:22;;28345:60;;;:::o;28411:132::-;28478:4;28501:3;28493:11;;28531:4;28526:3;28522:14;28514:22;;28483:60;;;:::o;28549:114::-;28616:6;28650:5;28644:12;28634:22;;28623:40;;;:::o;28669:114::-;28736:6;28770:5;28764:12;28754:22;;28743:40;;;:::o;28789:99::-;28841:6;28875:5;28869:12;28859:22;;28848:40;;;:::o;28894:113::-;28964:4;28996;28991:3;28987:14;28979:22;;28969:38;;;:::o;29013:113::-;29083:4;29115;29110:3;29106:14;29098:22;;29088:38;;;:::o;29132:184::-;29231:11;29265:6;29260:3;29253:19;29305:4;29300:3;29296:14;29281:29;;29243:73;;;;:::o;29322:184::-;29421:11;29455:6;29450:3;29443:19;29495:4;29490:3;29486:14;29471:29;;29433:73;;;;:::o;29512:169::-;29596:11;29630:6;29625:3;29618:19;29670:4;29665:3;29661:14;29646:29;;29608:73;;;;:::o;29687:305::-;29727:3;29746:20;29764:1;29746:20;:::i;:::-;29741:25;;29780:20;29798:1;29780:20;:::i;:::-;29775:25;;29934:1;29866:66;29862:74;29859:1;29856:81;29853:2;;;29940:18;;:::i;:::-;29853:2;29984:1;29981;29977:9;29970:16;;29731:261;;;;:::o;29998:191::-;30038:4;30058:20;30076:1;30058:20;:::i;:::-;30053:25;;30092:20;30110:1;30092:20;:::i;:::-;30087:25;;30131:1;30128;30125:8;30122:2;;;30136:18;;:::i;:::-;30122:2;30181:1;30178;30174:9;30166:17;;30043:146;;;;:::o;30195:96::-;30232:7;30261:24;30279:5;30261:24;:::i;:::-;30250:35;;30240:51;;;:::o;30297:90::-;30331:7;30374:5;30367:13;30360:21;30349:32;;30339:48;;;:::o;30393:149::-;30429:7;30469:66;30462:5;30458:78;30447:89;;30437:105;;;:::o;30548:126::-;30585:7;30625:42;30618:5;30614:54;30603:65;;30593:81;;;:::o;30680:77::-;30717:7;30746:5;30735:16;;30725:32;;;:::o;30763:154::-;30847:6;30842:3;30837;30824:30;30909:1;30900:6;30895:3;30891:16;30884:27;30814:103;;;:::o;30923:307::-;30991:1;31001:113;31015:6;31012:1;31009:13;31001:113;;;31100:1;31095:3;31091:11;31085:18;31081:1;31076:3;31072:11;31065:39;31037:2;31034:1;31030:10;31025:15;;31001:113;;;31132:6;31129:1;31126:13;31123:2;;;31212:1;31203:6;31198:3;31194:16;31187:27;31123:2;30972:258;;;;:::o;31236:320::-;31280:6;31317:1;31311:4;31307:12;31297:22;;31364:1;31358:4;31354:12;31385:18;31375:2;;31441:4;31433:6;31429:17;31419:27;;31375:2;31503;31495:6;31492:14;31472:18;31469:38;31466:2;;;31522:18;;:::i;:::-;31466:2;31287:269;;;;:::o;31562:281::-;31645:27;31667:4;31645:27;:::i;:::-;31637:6;31633:40;31775:6;31763:10;31760:22;31739:18;31727:10;31724:34;31721:62;31718:2;;;31786:18;;:::i;:::-;31718:2;31826:10;31822:2;31815:22;31605:238;;;:::o;31849:233::-;31888:3;31911:24;31929:5;31911:24;:::i;:::-;31902:33;;31957:66;31950:5;31947:77;31944:2;;;32027:18;;:::i;:::-;31944:2;32074:1;32067:5;32063:13;32056:20;;31892:190;;;:::o;32088:180::-;32136:77;32133:1;32126:88;32233:4;32230:1;32223:15;32257:4;32254:1;32247:15;32274:180;32322:77;32319:1;32312:88;32419:4;32416:1;32409:15;32443:4;32440:1;32433:15;32460:180;32508:77;32505:1;32498:88;32605:4;32602:1;32595:15;32629:4;32626:1;32619:15;32646:102;32687:6;32738:2;32734:7;32729:2;32722:5;32718:14;32714:28;32704:38;;32694:54;;;:::o;32754:245::-;32894:34;32890:1;32882:6;32878:14;32871:58;32963:28;32958:2;32950:6;32946:15;32939:53;32860:139;:::o;33005:225::-;33145:34;33141:1;33133:6;33129:14;33122:58;33214:8;33209:2;33201:6;33197:15;33190:33;33111:119;:::o;33236:226::-;33376:34;33372:1;33364:6;33360:14;33353:58;33445:9;33440:2;33432:6;33428:15;33421:34;33342:120;:::o;33468:238::-;33608:34;33604:1;33596:6;33592:14;33585:58;33677:21;33672:2;33664:6;33660:15;33653:46;33574:132;:::o;33712:224::-;33852:34;33848:1;33840:6;33836:14;33829:58;33921:7;33916:2;33908:6;33904:15;33897:32;33818:118;:::o;33942:222::-;34082:34;34078:1;34070:6;34066:14;34059:58;34151:5;34146:2;34138:6;34134:15;34127:30;34048:116;:::o;34170:229::-;34310:34;34306:1;34298:6;34294:14;34287:58;34379:12;34374:2;34366:6;34362:15;34355:37;34276:123;:::o;34405:173::-;34545:25;34541:1;34533:6;34529:14;34522:49;34511:67;:::o;34584:180::-;34724:32;34720:1;34712:6;34708:14;34701:56;34690:74;:::o;34770:182::-;34910:34;34906:1;34898:6;34894:14;34887:58;34876:76;:::o;34958:225::-;35098:34;35094:1;35086:6;35082:14;35075:58;35167:8;35162:2;35154:6;35150:15;35143:33;35064:119;:::o;35189:234::-;35329:34;35325:1;35317:6;35313:14;35306:58;35398:17;35393:2;35385:6;35381:15;35374:42;35295:128;:::o;35429:177::-;35569:29;35565:1;35557:6;35553:14;35546:53;35535:71;:::o;35612:169::-;35752:21;35748:1;35740:6;35736:14;35729:45;35718:63;:::o;35787:222::-;35927:34;35923:1;35915:6;35911:14;35904:58;35996:5;35991:2;35983:6;35979:15;35972:30;35893:116;:::o;36015:225::-;36155:34;36151:1;36143:6;36139:14;36132:58;36224:8;36219:2;36211:6;36207:15;36200:33;36121:119;:::o;36246:237::-;36386:34;36382:1;36374:6;36370:14;36363:58;36455:20;36450:2;36442:6;36438:15;36431:45;36352:131;:::o;36489:122::-;36562:24;36580:5;36562:24;:::i;:::-;36555:5;36552:35;36542:2;;36601:1;36598;36591:12;36542:2;36532:79;:::o;36617:116::-;36687:21;36702:5;36687:21;:::i;:::-;36680:5;36677:32;36667:2;;36723:1;36720;36713:12;36667:2;36657:76;:::o;36739:120::-;36811:23;36828:5;36811:23;:::i;:::-;36804:5;36801:34;36791:2;;36849:1;36846;36839:12;36791:2;36781:78;:::o;36865:122::-;36938:24;36956:5;36938:24;:::i;:::-;36931:5;36928:35;36918:2;;36977:1;36974;36967:12;36918:2;36908:79;:::o
Swarm Source
ipfs://31628b23795ebcc7aee1a200d8f4a4c3f997784b255f55f068073ba235c5f14a