Feature Tip: Add private address tag to any address under My Name Tag !
ERC-721
Source Code
Overview
Max Total Supply
16 OSM
Holders
16
Transfers
-
0 (0%)
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
| # | Exchange | Pair | Price | 24H Volume | % Volume |
|---|
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
OSMSubscription
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "./TokenReceiver.sol";
import "./Mintable.sol";
import "./Nameable.sol";
import { DiscountIsInvalid } from "./SetSubscribable.sol";
error ZeroAddress(address zero);
contract OSMSubscription is TokenReceiver {
event CommissionPaid(address wallet, uint256 amount);
constructor(string memory name, string memory symbol) Subscribable(name,symbol) {}
function payOutFees(uint256 numberOfDays, string memory discountCode) internal {
uint256 fee = determineFee(numberOfDays,discountCode);
address payable partner = payable(subs.promoDiscounts[discountCode].partner);
uint256 commission = determineCommission(fee, discountCode);
if (commission > 0) {
partner.transfer(commission);
emit CommissionPaid(subs.promoDiscounts[discountCode].partner, commission);
}
OSM_TREASURY_WALLET.transfer(fee-commission);
subs.promoDiscounts[discountCode].timesUsed = subs.promoDiscounts[discountCode].timesUsed + 1;
}
function mint(uint256 numberOfDays) external payable {
payOutFees(numberOfDays, blank);
_mintTokenFor(msg.sender,numberOfDays);
}
function discountMint(uint256 numberOfDays, string calldata discountCode) external payable {
if (!subs.promoDiscounts[discountCode].exists || subs.promoDiscounts[discountCode].expires < block.timestamp) {
revert DiscountIsInvalid(discountCode);
}
payOutFees(numberOfDays, discountCode);
subs.promoDiscounts[discountCode].timesUsed = subs.promoDiscounts[discountCode].timesUsed + 1;
_mintTokenFor(msg.sender,numberOfDays,discountCode);
}
function mintForRecipient(address recipient, uint256 numberOfDays) external onlyOwner {
establishSubscription(incrementMint(recipient),numberOfDays);
}
function _mintTokenFor(address recipient, uint256 numberOfDays) internal {
_mintTokenFor(recipient,numberOfDays,blank);
}
function _mintTokenFor(address recipient, uint256 numberOfDays, string memory discountCode) internal {
commitSubscription(incrementMint(recipient), numberOfDays, discountCode);
}
function incrementMint(address recipient) private returns (uint256) {
uint256 tokenId = totalSupply()+1;
_mint(recipient,tokenId);
return tokenId;
}
function renewOSM(uint256 tokenId, uint256 numberOfDays) public payable {
renewOSM(tokenId, numberOfDays, blank);
}
function renewOSM(uint256 tokenId, uint256 numberOfDays, string memory discountCode) public payable {
payOutFees(numberOfDays, discountCode);
renewSubscription(tokenId, numberOfDays, discountCode);
}
}// 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.8.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface 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.8.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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or 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 {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @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 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/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
pragma solidity ^0.8.17;
import "./Ownable.sol";
import "./Nameable.sol";
import { TokenNonOwner } from "./SetOwnerEnumerable.sol";
import { OwnerEnumerable } from "./OwnerEnumerable.sol";
import { SetApprovable, ApprovableData, TokenNonExistent } from "./SetApprovable.sol";
abstract contract Approvable is OwnerEnumerable {
using SetApprovable for ApprovableData;
ApprovableData approvable;
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return approvable.isApprovedForAll(owner,operator);
}
function approve(address to, uint256 tokenId) public virtual override {
if (ownerOf(tokenId) != msg.sender) {
revert TokenNonOwner(msg.sender,tokenId);
}
approvable.approveForToken(to, tokenId);
emit Approval(ownerOf(tokenId), to, tokenId);
}
function setApprovalForAll(address operator, bool approved) public virtual override {
if (approved) {
approvable.approveForContract(operator);
} else {
approvable.revokeApprovalForContract(operator, msg.sender);
}
}
function validateApprovedOrOwner(address spender, uint256 tokenId) internal view {
address owner = ownerOf(tokenId);
if (!(spender == owner || isApprovedForAll(owner, spender) || approvable.getApproved(tokenId) == spender)) {
revert TokenNonOwner(spender, tokenId);
}
}
function getApproved(uint256 tokenId) public view virtual override returns (address) {
requireMinted(tokenId);
return approvable.tokens[tokenId].approval;
}
function revokeTokenApproval(uint256 tokenId) internal {
approvable.revokeTokenApproval(tokenId);
}
function revokeApprovals(address holder) internal {
approvable.revokeApprovals(holder,tokensOwnedBy(holder));
}
/**
* @dev Reverts if the `tokenId` has not been minted yet.
*/
function requireMinted(uint256 tokenId) internal view virtual {
if (!exists(tokenId)) {
revert TokenNonExistent(tokenId);
}
}
function exists(uint256 tokenId) internal view virtual returns (bool) {
return approvable.tokens[tokenId].exists;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { SetContractable, ContractableData, AllowedContract, AllowedPath } from "./SetContractable.sol";
import "./Mintable.sol";
abstract contract Contractable is Mintable {
using SetContractable for ContractableData;
ContractableData contractables;
function balanceOfAllowance(address wallet) public view returns (uint256) {
return contractables.balanceOfAllowance(wallet);
}
function allowances(address wallet) public view returns (AllowedContract [] memory) {
return contractables.allowances(wallet);
}
function allowContract(address allowed, string calldata urlPath, string calldata erc, uint256 balanceRequired, bool isStaking, bool isProxy) public {
contractables.allowContract(allowed, urlPath, erc, balanceRequired, isStaking, isProxy);
}
function pathAllows(string calldata path) public view returns (AllowedPath memory) {
return contractables.pathAllows(path);
}
function revokeContract(address revoked) public {
contractables.revokeContract(revoked);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "./Ownable.sol";
import { SetFlexibleMetadataData, FlexibleMetadataData } from "./SetFlexibleMetadata.sol";
uint256 constant DEFAULT = 1;
uint256 constant FLAG = 2;
uint256 constant PRE = 3;
abstract contract FlexibleMetadata is Ownable, Context, ERC165, IERC721, IERC721Metadata {
using SetFlexibleMetadataData for FlexibleMetadataData;
FlexibleMetadataData flexible;
string tokenName;
string tokenSymbol;
constructor(string memory _name, string memory _symbol) {
tokenName = _name;
tokenSymbol = _symbol;
}
function name() public virtual override view returns (string memory) {
return tokenName;
}
function symbol() public virtual override view returns (string memory) {
return tokenSymbol;
}
function setContractUri(string memory uri) public onlyOwner {
flexible.setContractMetadataURI(uri);
}
function reveal(bool _reveal) public onlyOwner {
flexible.reveal(_reveal);
}
function setTokenUri(string memory uri, uint256 tokenType) public {
if (tokenType == FLAG) {
flexible.setFlaggedTokenMetadataURI(uri);
}
else if (tokenType == PRE) {
flexible.setPrerevealTokenMetadataURI(uri);
} else {
flexible.setDefaultTokenMetadataURI(uri);
}
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165,IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
return flexible.getTokenMetadata(tokenId);
}
function contractURI() public view returns (string memory) {
return flexible.getContractMetadata();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "./Approvable.sol";
import { SetLockable, LockableStatus, LockableData, WalletLockedByOwner } from "./SetLockable.sol";
abstract contract Lockable is Approvable {
using SetLockable for LockableData;
LockableData lockable;
function custodianOf(uint256 id)
public
view
returns (address)
{
return lockable.findCustodian(ownerOf(id));
}
function lockWallet(uint256 id) public {
address owner = ownerOf(id);
revokeApprovals(owner);
lockable.lockWallet(owner);
}
function unlockWallet(uint256 id) public {
lockable.unlockWallet(ownerOf(id));
}
function _forceUnlock(uint256 id) internal {
lockable.forceUnlock(ownerOf(id));
}
function setCustodian(uint256 id, address custodianAddress) public {
lockable.setCustodian(custodianAddress,ownerOf(id));
}
function isLocked(uint256 id) public view returns (bool) {
return lockable.lockableStatus[ownerOf(id)].isLocked;
}
function lockedSince(uint256 id) public view returns (uint256) {
return lockable.lockableStatus[ownerOf(id)].lockedAt;
}
function validateLock(uint256 tokenId) internal view {
if (isLocked(tokenId)) {
revert WalletLockedByOwner();
}
}
function initializeLockable(address wallet, LockableStatus memory status) internal {
lockable.lockableStatus[wallet] = status;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "./Lockable.sol";
import { LockableStatus } from "./SetLockable.sol";
error InvalidTransferRecipient();
error NotApprovedOrOwner();
error InvalidOwner();
error OnlyOneSubscriptionPerWallet(uint256 balance);
error ContractIsNot721Receiver();
abstract contract LockableTransferrable is Lockable {
using Address for address;
function approve(address to, uint256 tokenId) public virtual override {
validateLock(tokenId);
super.approve(to,tokenId);
}
function setApprovalForAll(address operator, bool approved) public virtual override {
validateLock(tokensOwnedBy(msg.sender)[0]);
super.setApprovalForAll(operator,approved);
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
validateApprovedOrOwner(msg.sender, tokenId);
validateLock(tokenId);
_transfer(from,to,tokenId);
}
function _transfer(
address from,
address to,
uint256 tokenId
) internal {
if (balanceOf(to) > 0) {
revert OnlyOneSubscriptionPerWallet(balanceOf(to));
}
if(to == address(0)) {
revert InvalidTransferRecipient();
}
revokeTokenApproval(tokenId);
swapOwner(from,to,tokenId);
completeTransfer(from,to,tokenId);
}
function completeTransfer(
address from,
address to,
uint256 tokenId) internal {
emit Transfer(from, to, tokenId);
address[] memory approvedAll;
initializeLockable(to,LockableStatus(false,0,address(0),0,approvedAll,true));
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory data
) public virtual override {
validateApprovedOrOwner(msg.sender, tokenId);
validateLock(tokenId);
_safeTransfer(from, to, tokenId, data);
}
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory data
) internal virtual {
if (!_checkOnERC721Received(from, to, tokenId, data)) {
revert ContractIsNot721Receiver();
}
_transfer(from, to, tokenId);
}
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert InvalidTransferRecipient();
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "./LockableTransferrable.sol";
error InvalidRecipient(address zero);
error TokenAlreadyMinted(uint256 tokenId);
error MintIsNotLive();
abstract contract Mintable is LockableTransferrable {
bool isLive;
uint256 tokenCount;
function setMintLive(bool _isLive) public onlyOwner {
isLive = _isLive;
}
function _mint(address to, uint256 tokenId) internal virtual {
if (!isLive) {
revert MintIsNotLive();
}
if (to == address(0)) {
revert InvalidRecipient(to);
}
if (exists(tokenId)) {
revert TokenAlreadyMinted(tokenId);
}
tokenCount +=1;
enumerateMint(to, tokenId);
completeTransfer(address(0),to,tokenId);
}
function totalSupply() public view returns (uint256) {
return tokenCount;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
abstract contract Nameable is IERC721Metadata {
string tokenName;
string tokenSymbol;
constructor(string memory _name, string memory _symbol) {
tokenName = _name;
tokenSymbol = _symbol;
}
function name() public virtual override view returns (string memory) {
return tokenName;
}
function symbol() public virtual override view returns (string memory) {
return tokenSymbol;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/**
* @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 {
address private _owner;
error CallerIsNotOwner(address caller);
error OwnerCannotBeZeroAddress();
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(msg.sender);
}
/**
* @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 {
if (owner() != msg.sender) {
revert CallerIsNotOwner(msg.sender);
}
}
/**
* @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 {
if(newOwner == address(0)) {
revert OwnerCannotBeZeroAddress();
}
_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
pragma solidity ^0.8.17;
import { SetOwnerEnumerable, OwnerEnumerableData, TokenNonOwner, InvalidOwner } from "./SetOwnerEnumerable.sol";
import { FlexibleMetadata } from "./FlexibleMetadata.sol";
abstract contract OwnerEnumerable is FlexibleMetadata {
using SetOwnerEnumerable for OwnerEnumerableData;
OwnerEnumerableData enumerable;
function ownerOf(uint256 tokenId) public view returns (address) {
return enumerable.ownerOf(tokenId);
}
function tokensOwnedBy(address holder) public view returns (uint256[] memory) {
return enumerable.findTokensOwned(holder);
}
function balanceOf(address owner) public view virtual override returns (uint256) {
validateNonZeroAddress(owner);
return enumerable.ownedTokens[owner].length;
}
function validateNonZeroAddress(address owner) internal pure {
if(owner == address(0)) {
revert InvalidOwner();
}
}
function enumerateMint(address to, uint256 tokenId) internal {
enumerable.addTokenToEnumeration(to, tokenId);
}
function swapOwner(address from, address to, uint256 tokenId) internal {
enumerable.removeTokenFromEnumeration(from, tokenId);
enumerable.removeTokenFromEnumeration(from, tokenId);
enumerable.addTokenToEnumeration(to, tokenId);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
struct ApprovableData {
mapping(address => uint256) contractApprovals;
mapping(address => address[]) approvedForAll;
mapping(address => mapping(address => uint256)) approvedForAllIndex;
mapping(uint256 => uint256) tokenApprovals;
mapping(uint256 => TokenApproval[]) approvedForToken;
mapping(uint256 => mapping(address => uint256)) approvedForTokenIndex;
mapping(uint256 => TokenApproval) tokens;
bool exists;
}
struct TokenApproval {
address approval;
bool exists;
}
error AlreadyApproved(address operator, uint256 tokenId);
error AlreadyApprovedContract(address operator);
error AlreadyRevoked(address operator, uint256 tokenId);
error AlreadyRevokedContract(address operator);
error TokenNonExistent(uint256 tokenId);
library SetApprovable {
/**
* @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);
function isApprovedForAll(ApprovableData storage self, address owner, address operator) public view returns (bool) {
return self.approvedForAll[owner].length > self.approvedForAllIndex[owner][operator] ?
(self.approvedForAll[owner][self.approvedForAllIndex[owner][operator]] != address(0)) :
false;
}
function revokeApprovals(ApprovableData storage self, address owner, uint256[] memory ownedTokens) public {
for (uint256 i = 0; i < ownedTokens.length; i++) {
revokeTokenApproval(self,ownedTokens[i]);
}
address[] memory contractApprovals = self.approvedForAll[owner];
for (uint256 i = 0; i < contractApprovals.length; i++) {
address approved = contractApprovals[i];
revokeApprovalForContract(self, approved, owner);
}
}
function revokeTokenApproval(ApprovableData storage self, uint256 token) public {
TokenApproval[] memory approvals = self.approvedForToken[token];
for (uint256 j = 0; j < approvals.length; j++) {
revokeApprovalForToken(self, approvals[j].approval, token);
}
}
function getApproved(ApprovableData storage self, uint256 tokenId) public view returns (address) {
return self.approvedForToken[tokenId].length > 0 ? self.approvedForToken[tokenId][0].approval : address(0);
}
function approveForToken(ApprovableData storage self, address operator, uint256 tokenId) public {
uint256 index = self.approvedForTokenIndex[tokenId][operator];
if (index < self.approvedForToken[tokenId].length && self.approvedForToken[tokenId][index].exists) {
revert AlreadyApproved(operator, tokenId);
}
self.approvedForToken[tokenId].push(TokenApproval(operator,true));
self.approvedForTokenIndex[tokenId][operator] = self.approvedForToken[tokenId].length-1;
self.tokenApprovals[tokenId]++;
emit Approval(msg.sender, operator, tokenId);
}
function revokeApprovalForToken(ApprovableData storage self, address revoked, uint256 tokenId) public {
uint256 index = self.approvedForTokenIndex[tokenId][revoked];
if (!self.approvedForToken[tokenId][index].exists) {
revert AlreadyRevoked(revoked,tokenId);
}
// When the token to delete is not the last token, the swap operation is unnecessary
if (index != self.approvedForToken[tokenId].length - 1) {
TokenApproval storage tmp = self.approvedForToken[tokenId][self.approvedForToken[tokenId].length - 1];
self.approvedForToken[tokenId][self.approvedForToken[tokenId].length - 1] = self.approvedForToken[tokenId][index];
self.approvedForToken[tokenId][index] = tmp;
self.approvedForTokenIndex[tokenId][tmp.approval] = index;
}
// This also deletes the contents at the last position of the array
delete self.approvedForTokenIndex[tokenId][revoked];
self.approvedForToken[tokenId].pop();
self.tokenApprovals[tokenId]--;
}
function approveForContract(ApprovableData storage self, address operator) public {
uint256 index = self.approvedForAllIndex[msg.sender][operator];
if (self.approvedForAll[msg.sender].length > index &&
self.approvedForAll[msg.sender][index] != address(0)) {
revert AlreadyApprovedContract(self.approvedForAll[msg.sender][index]);
}
self.approvedForAll[msg.sender].push(operator);
self.approvedForAllIndex[msg.sender][operator] = self.approvedForAll[msg.sender].length-1;
self.contractApprovals[msg.sender]++;
emit ApprovalForAll(msg.sender, operator, true);
}
function revokeApprovalForContract(ApprovableData storage self, address revoked, address owner) public {
uint256 index = self.approvedForAllIndex[owner][revoked];
address revokee = self.approvedForAll[owner][index];
if (revokee != revoked) {
revert AlreadyRevokedContract(revoked);
}
// When the token to delete is not the last token, the swap operation is unnecessary
if (index != self.approvedForAll[owner].length - 1) {
address tmp = self.approvedForAll[owner][self.approvedForAll[owner].length - 1];
self.approvedForAll[owner][self.approvedForAll[owner].length - 1] = self.approvedForAll[owner][index];
self.approvedForAll[owner][index] = tmp;
self.approvedForAllIndex[owner][tmp] = index;
}
// This also deletes the contents at the last position of the array
delete self.approvedForAllIndex[owner][revoked];
self.approvedForAll[owner].pop();
self.contractApprovals[owner]--;
emit ApprovalForAll(owner, revoked, false);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
struct AllowedContract {
address addressed;
string urlPath;
string erc;
uint256 balanceRequired;
bool isStaking;
bool isProxy;
bool exists;
}
struct AllowedPath {
address[] addresses;
address wallet;
bool exists;
}
struct ContractableData {
mapping(address => AllowedContract[]) contractAllowlist;
mapping(string => AllowedPath) paths;
mapping(address => mapping(address => uint256)) contractIndexList;
mapping(address => uint256) allowanceBalances;
}
library SetContractable {
error AlreadyAllowed(address requester, address contracted);
error PathAlreadyInUse(string path);
error PathDoesNotExist(string path);
error WTF(bool success,address wtf);
error IsNotAllowed(address requester, address contracted);
function balanceOfAllowance(ContractableData storage self, address wallet) public view returns (uint256) {
return self.allowanceBalances[wallet];
}
function allowances(ContractableData storage self, address wallet) public view returns (AllowedContract [] memory) {
return self.contractAllowlist[wallet];
}
function addAllowance(ContractableData storage self, address allowed, string calldata urlPath, string calldata erc, uint256 balanceRequired, bool isStaking, bool isProxy) public {
self.contractIndexList[msg.sender][allowed] = balanceOfAllowance(self,msg.sender);
self.contractAllowlist[msg.sender].push(AllowedContract(allowed,urlPath,erc,balanceRequired,isStaking,isProxy,true));
self.allowanceBalances[msg.sender]++;
}
function allowContract(
ContractableData storage self,
address allowed,
string calldata urlPath,
string calldata erc,
uint256 balanceRequired,
bool isStaking,
bool isProxy) public {
if (self.paths[urlPath].exists && self.paths[urlPath].wallet != msg.sender) {
revert PathAlreadyInUse(urlPath);
} else if (balanceOfAllowance(self, msg.sender) > 0 && !self.paths[urlPath].exists) {
for (uint256 i = 0; i < balanceOfAllowance(self, msg.sender); i++) {
AllowedContract storage existing = self.contractAllowlist[msg.sender][i];
if (self.paths[existing.urlPath].exists) {
delete self.paths[existing.urlPath];
}
existing.urlPath = urlPath;
}
}
if (balanceOfAllowance(self,msg.sender) != 0) {
uint256 index = self.contractIndexList[msg.sender][allowed];
if (self.contractAllowlist[msg.sender][index].addressed == allowed) {
revert AlreadyAllowed(msg.sender,allowed);
}
}
addAllowance(self,allowed,urlPath,erc,balanceRequired,isStaking,isProxy);
address[] memory addressed = new address[](balanceOfAllowance(self, msg.sender));
for (uint256 i = 0; i < balanceOfAllowance(self, msg.sender); i++) {
addressed[i] = self.contractAllowlist[msg.sender][i].addressed;
}
self.paths[urlPath] = AllowedPath(addressed,msg.sender,balanceOfAllowance(self, msg.sender) > 0);
}
function removeAllowance(ContractableData storage self, address allowed, string calldata urlPath, string calldata erc, uint256 balanceRequired, bool isStaking, bool isProxy) public {
self.contractIndexList[msg.sender][allowed] = balanceOfAllowance(self,msg.sender);
self.contractAllowlist[msg.sender].push(AllowedContract(allowed,urlPath,erc,balanceRequired,isStaking,isProxy,true));
self.allowanceBalances[msg.sender]++;
}
function revokeContract(ContractableData storage self, address revoked) public {
uint256 length = self.contractAllowlist[msg.sender].length;
uint256 revokedIndex = self.contractIndexList[msg.sender][revoked];
AllowedContract storage revokee = self.contractAllowlist[msg.sender][revokedIndex];
// When the token to delete is the last token, the swap operation is unnecessary
if (revokedIndex < length - 1) {
AllowedContract memory lastItem = self.contractAllowlist[msg.sender][length - 1];
self.contractAllowlist[msg.sender][revokedIndex] = lastItem; // Move the last token to the slot of the to-delete token
self.contractIndexList[msg.sender][lastItem.addressed] = revokedIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete self.contractIndexList[msg.sender][revoked];
self.contractAllowlist[msg.sender].pop();
self.allowanceBalances[msg.sender]--;
uint256 balanced = balanceOfAllowance(self, msg.sender);
if (balanced > 0) {
address[] memory addressed = new address[](balanceOfAllowance(self, msg.sender));
for (uint256 i = 0; i < balanceOfAllowance(self, msg.sender); i++) {
addressed[i] = self.contractAllowlist[msg.sender][i].addressed;
}
self.paths[revokee.urlPath] = AllowedPath(addressed,msg.sender,true);
} else {
address[] memory addressed = new address[](0);
self.paths[revokee.urlPath] = AllowedPath(addressed,msg.sender,false);
}
}
function pathAllows(ContractableData storage self, string calldata path) public view returns (AllowedPath memory) {
if (!self.paths[path].exists) {
revert PathDoesNotExist(path);
}
return self.paths[path];
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
struct FlexibleMetadataData {
string defaultTokenMetadata;
string prerevealTokenMetadata;
string flaggedTokenMetadata;
string contractMetadata;
mapping(uint256 => bool) tokenFlag;
bool tokenReveal;
}
bytes16 constant _SYMBOLS = "0123456789abcdef";
library SetFlexibleMetadataData {
function setDefaultTokenMetadataURI(FlexibleMetadataData storage self, string memory uri) public {
self.defaultTokenMetadata = uri;
}
function setPrerevealTokenMetadataURI(FlexibleMetadataData storage self, string memory uri) public {
self.prerevealTokenMetadata = uri;
}
function setFlaggedTokenMetadataURI(FlexibleMetadataData storage self, string memory uri) public {
self.flaggedTokenMetadata = uri;
}
function setContractMetadataURI(FlexibleMetadataData storage self, string memory uri) public {
self.contractMetadata = uri;
}
function reveal(FlexibleMetadataData storage self, bool revealed) public {
self.tokenReveal = revealed;
}
function flagToken(FlexibleMetadataData storage self, uint256 tokenId, bool flagged) public {
self.tokenFlag[tokenId] = flagged;
}
function getTokenMetadata(FlexibleMetadataData storage self, uint256 tokenId) public view returns (string memory) {
if (self.tokenFlag[tokenId]) {
return encodeURI(self.flaggedTokenMetadata,tokenId);
}
if (!self.tokenReveal) {
return encodeURI(self.prerevealTokenMetadata,tokenId);
}
return encodeURI(self.defaultTokenMetadata,tokenId);
}
function getContractMetadata(FlexibleMetadataData storage self) public view returns (string memory) {
return self.contractMetadata;
}
function encodeURI(string storage uri, uint256 tokenId) public pure returns (string memory) {
return string(abi.encodePacked(uri, "/", toString(tokenId)));
}
function toString(uint256 value) public pure returns (string memory) {
unchecked {
uint256 length = log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
function log10(uint256 value) public pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { InvalidOwner } from "./SetOwnerEnumerable.sol";
struct LockableData {
mapping(address => uint256) lockableStatusIndex;
mapping(address => LockableStatus) lockableStatus;
}
struct LockableStatus {
bool isLocked;
uint256 lockedAt;
address custodian;
uint256 balance;
address[] approvedAll;
bool exists;
}
uint64 constant MAX_INT = 2**64 - 1;
error OnlyCustodianCanLock();
error OnlyOwnerCanSetCustodian();
error WalletLockedByOwner();
library SetLockable {
function lockWallet(LockableData storage self, address holder) public {
LockableStatus storage status = self.lockableStatus[holder];
if (msg.sender != status.custodian) {
revert OnlyCustodianCanLock();
}
status.isLocked = true;
status.lockedAt = block.timestamp;
}
function unlockWallet(LockableData storage self, address holder) public {
LockableStatus storage status = self.lockableStatus[holder];
if (msg.sender != status.custodian) {
revert OnlyCustodianCanLock();
}
status.isLocked = false;
status.lockedAt = MAX_INT;
}
function setCustodian(LockableData storage self, address custodianAddress, address holder) public {
if (msg.sender != holder) {
revert OnlyOwnerCanSetCustodian();
}
LockableStatus storage status = self.lockableStatus[holder];
status.custodian = custodianAddress;
}
function findCustodian(LockableData storage self, address wallet) public view returns (address) {
return self.lockableStatus[wallet].custodian;
}
function forceUnlock(LockableData storage self, address owner) public {
LockableStatus storage status = self.lockableStatus[owner];
status.isLocked = false;
status.lockedAt = MAX_INT;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
struct OwnerEnumerableData {
mapping(uint256 => TokenOwnership) tokens;
mapping(address => uint256[]) ownedTokens;
mapping(address => mapping(uint256 => uint256)) ownedTokensIndex;
uint256 totalSupply;
}
struct TokenOwnership {
address ownedBy;
bool exists;
}
error TokenNonOwner(address requester, uint256 tokenId);
error InvalidOwner();
library SetOwnerEnumerable {
function addTokenToEnumeration(OwnerEnumerableData storage self, address to, uint256 tokenId) public {
self.ownedTokens[to].push(tokenId);
uint256 length = self.ownedTokens[to].length;
self.ownedTokensIndex[to][tokenId] = length-1;
self.tokens[tokenId] = TokenOwnership(to,true);
}
function removeTokenFromEnumeration(OwnerEnumerableData storage self, address to, uint256 tokenId) public {
uint256 length = self.ownedTokens[to].length;
if (self.ownedTokensIndex[to][tokenId] > 0 && self.ownedTokensIndex[to][tokenId] != length - 1) {
uint256 lastTokenId = self.ownedTokens[to][length - 1];
self.ownedTokens[to][self.ownedTokensIndex[to][tokenId]] = lastTokenId;
self.ownedTokensIndex[to][lastTokenId] = self.ownedTokensIndex[to][tokenId];
}
delete self.ownedTokensIndex[to][tokenId];
if (self.ownedTokens[to].length > 0) {
self.ownedTokens[to].pop();
}
}
function findTokensOwned(OwnerEnumerableData storage self, address wallet) public view returns (uint256[] storage) {
return self.ownedTokens[wallet];
}
function tokenIndex(OwnerEnumerableData storage self, address wallet, uint256 index) public view returns (uint256) {
return self.ownedTokens[wallet][index];
}
function ownerOf(OwnerEnumerableData storage self, uint256 tokenId) public view returns (address) {
address owner = self.tokens[tokenId].ownedBy;
if (owner == address(0)) {
revert TokenNonOwner(owner,tokenId);
}
return owner;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
struct ReceivableData {
mapping(address => mapping(address => uint256[])) receivedTokens;
mapping(address => address[]) stakedContracts;
mapping(address => mapping(address => uint256)) stakedContractIndex;
mapping(address => mapping(uint256 => uint256)) receivedTokensIndex;
mapping(address => mapping(address => uint256)) walletBalances;
}
interface Holdable {
function balanceOf(address owner) external returns (uint256);
function ownerOf(uint256 tokenId) external returns (address);
}
error MintNotLive();
error ReceivedTokenNonExistent(uint256 tokenId);
error ReceivedTokenNonOwner(address requester, uint256 tokenId);
library SetReceivable {
function balanceOfWallet(ReceivableData storage self, address wallet, address contracted) public view returns (uint256) {
return self.walletBalances[wallet][contracted];
}
function receivedFromWallet(ReceivableData storage self, address wallet, address contracted) public view returns (uint256[] memory) {
return self.receivedTokens[wallet][contracted];
}
function _addTokenToReceivedEnumeration(ReceivableData storage self, address from, address contracted, uint256 tokenId) public {
uint256 length = balanceOfWallet(self,from,contracted);
if (length >= self.receivedTokens[from][contracted].length) {
length = self.receivedTokens[from][contracted].length;
self.receivedTokens[from][contracted].push(tokenId);
// revert ReceivedTokenNonExistent(self.receivedTokens[from][contracted][0]);
} else {
self.receivedTokens[from][contracted][length] = tokenId;
}
self.receivedTokensIndex[contracted][tokenId] = length;
self.walletBalances[from][contracted]++;
if (self.receivedTokens[from][contracted].length < 1) {
revert ReceivedTokenNonExistent(tokenId);
}
if (length < 1) {
self.stakedContracts[from].push(contracted);
self.stakedContractIndex[from][contracted] = self.stakedContracts[from].length;
}
}
function _removeTokenFromReceivedEnumeration(ReceivableData storage self, address from, address contracted, uint256 tokenId) public {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
// if (self.receivedTokens[from][contracted].length < 1) {
// revert ReceivedTokenNonExistent(tokenId);
// }
// When the token to delete is the last token, the swap operation is unnecessary
if (self.receivedTokens[from][contracted].length > self.receivedTokensIndex[contracted][tokenId] &&
self.receivedTokensIndex[contracted][tokenId] != self.receivedTokens[from][contracted].length - 1) {
uint256 lastTokenId = self.receivedTokens[from][contracted][balanceOfWallet(self,from,contracted) - 1];
self.receivedTokens[from][contracted][self.receivedTokensIndex[contracted][tokenId]] = lastTokenId; // Move the last token to the slot of the to-delete token
self.receivedTokensIndex[contracted][lastTokenId] = self.receivedTokensIndex[contracted][tokenId]; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete self.receivedTokensIndex[contracted][tokenId];
self.receivedTokens[from][contracted].pop();
self.walletBalances[from][contracted]--;
uint256 left = balanceOfWallet(self,from,contracted);
if (left < 1) {
if (self.stakedContracts[from].length > self.stakedContractIndex[from][contracted] &&
self.stakedContractIndex[from][contracted] != self.stakedContracts[from].length - 1) {
address lastContract = self.stakedContracts[from][self.stakedContracts[from].length - 1];
self.stakedContracts[from][self.stakedContracts[from].length - 1] = contracted;
self.stakedContracts[from][self.stakedContractIndex[from][contracted]] = lastContract;
}
self.stakedContracts[from].pop();
delete self.stakedContractIndex[from][contracted];
}
}
function tokenReceivedByIndex(ReceivableData storage self, address wallet, address contracted, uint256 index) public view returns (uint256) {
return self.receivedTokens[wallet][contracted][index];
}
function swapOwner(ReceivableData storage self, address from, address to) public {
for (uint256 contractIndex = 0; contractIndex < self.stakedContracts[from].length; contractIndex++) {
address contractToSwap = self.stakedContracts[from][contractIndex];
uint256 tokenId = self.receivedTokens[from][contractToSwap][0];
while (self.receivedTokens[from][contractToSwap].length > 0) {
_removeTokenFromReceivedEnumeration(self,from,contractToSwap,tokenId);
_addTokenToReceivedEnumeration(self,to,contractToSwap,tokenId);
if ((self.receivedTokens[from][contractToSwap].length > 0)) {
tokenId = self.receivedTokens[from][contractToSwap][0];
}
}
}
}
function withdraw(ReceivableData storage self, address contracted, uint256[] calldata tokenIds) public {
for (uint256 i; i < tokenIds.length; i++) {
uint256 tokenId = tokenIds[i];
Holdable held = Holdable(contracted);
if (held.ownerOf(tokenId) != address(this)) {
revert ReceivedTokenNonOwner(address(this),tokenId);
}
// uint256 tokenIndex = self.receivedTokensIndex[contracted][tokenId];
// if (self.receivedTokens[msg.sender][contracted].length > tokenIndex &&
// tokenReceivedByIndex(self,msg.sender,contracted,tokenIndex) != tokenId) {
// revert ReceivedTokenNonOwner(msg.sender,tokenIndex);
// }
_removeTokenFromReceivedEnumeration(self,msg.sender,contracted,tokenId);
IERC721(contracted).safeTransferFrom(
address(this),
msg.sender,
tokenId,
""
);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
struct SubscriptionSpans {
uint256 one;
uint256 three;
uint256 six;
uint256 twelve;
}
struct FeeStructure {
uint256 baseMultiplier;
uint256 baseDiscount;
uint256 annual;
}
struct PromoDiscount {
uint256 amount;
uint256 commission;
uint256 timesUsed;
uint256 expires;
address partner;
bool exists;
}
struct SubscribableData {
// day number to rate
// mapping(uint256 => RateStructure) spanToRate;
// tokenId to expiration
mapping(uint256 => uint256) subscriptions;
mapping(string => PromoDiscount) promoDiscounts;
SubscriptionSpans subscriptionSpans;
FeeStructure feeStructure;
}
error InvalidNumberOfDays(uint256 numberOfDays);
error InvalidAmountForDays(uint256 numberOfDays, uint256 amount, uint256 required);
error DiscountIsInvalid(string discountCode);
address constant defaultPayable = 0x5aE09f46967A92f3cF976e98f82B6FDd00784815;
string constant blank = " ";
uint256 constant never = 9999999999999999999999999999;
library SetSubscribable {
event SubscriptionUpdate(uint256 indexed tokenId, uint256 expiration);
function initialize(SubscribableData storage self) public {
setSpans(self, 4 * 7, 12 * 7, 24 * 7, 48 * 7); // 4 weeks, 12 weeks, 24 weeks, 48 weeks
setFeeStructure(self,4, 25, 52); // base multiplier, base discount, annual period
self.promoDiscounts[blank] = PromoDiscount(0,0,0,never,defaultPayable,true);
}
function setSpans(SubscribableData storage self, uint256 one, uint256 three, uint256 six, uint256 twelve) public {
self.subscriptionSpans = SubscriptionSpans(one,three,six,twelve);
}
function setFeeStructure(SubscribableData storage self, uint256 multiplier, uint256 discount, uint256 annual) public {
self.feeStructure = FeeStructure(multiplier,discount,annual);
}
function setRateParams(SubscribableData storage self, uint256 multiplier, uint256 discount) public {
setSpans(self,28, 84, 168, 336);
setFeeStructure(self,multiplier, discount, 52);
}
function establishSubscription(SubscribableData storage self, uint256 tokenId, uint256 numberOfDays) public {
uint256 expiration;
if (block.timestamp > self.subscriptions[tokenId]) {
expiration = block.timestamp + numberOfDays * 1 days;
} else {
expiration = self.subscriptions[tokenId] + numberOfDays * 1 days;
}
self.subscriptions[tokenId] = expiration;
emit SubscriptionUpdate(tokenId, expiration);
}
function calculateExpiration(SubscribableData storage self, uint256 tokenId, uint256 numberOfDays) public view returns (uint256) {
if (block.timestamp > self.subscriptions[tokenId]) {
return block.timestamp + numberOfDays * 1 days;
}
return self.subscriptions[tokenId] + numberOfDays * 1 days;
}
function calculateBaseRate(SubscribableData storage self, uint256 numberOfDays) public view returns (uint256) {
uint256 discountMultiplier = numberOfDays == self.subscriptionSpans.one ? 0 :
numberOfDays == self.subscriptionSpans.three ? 1 :
numberOfDays == self.subscriptionSpans.six ? 2 :
3;
uint256 spans = numberOfDays / 7;
uint256 periodDiscount = discountMultiplier * self.feeStructure.baseDiscount * (1 ether);
return ((self.feeStructure.baseMultiplier * 100 * (1 ether)) - periodDiscount) / 100 / self.feeStructure.annual * spans;
}
function calculateDiscount(uint256 promoDiscount) public pure returns (uint256) {
return 100-promoDiscount;
}
function calculateFee(SubscribableData storage self, uint256 numberOfDays) public view returns (uint256) {
return calculateFee(self, numberOfDays, blank);
}
function calculateFee(SubscribableData storage self, uint256 numberOfDays, string memory discountCode) public view returns (uint256) {
validateDays(self,numberOfDays);
uint256 baseRate = calculateBaseRate(self,numberOfDays);
uint256 discount = calculateDiscount(self.promoDiscounts[discountCode].amount);
baseRate = baseRate * discount / 100;
return floor(baseRate);
}
function calculateCommission(SubscribableData storage self, uint256 originalAmount, string memory discountCode) public view returns (uint256) {
uint256 commissionRate = self.promoDiscounts[discountCode].commission > 0 ? 10000/self.promoDiscounts[discountCode].commission : 0;
uint256 commission = 0;
if (commissionRate >= 1) {
commission = originalAmount / commissionRate * 100;
}
return commission;
}
function validateDays(SubscribableData storage self, uint256 numberOfDays) public view {
if (numberOfDays != self.subscriptionSpans.one &&
numberOfDays != self.subscriptionSpans.three &&
numberOfDays != self.subscriptionSpans.six &&
numberOfDays != self.subscriptionSpans.twelve ) {
revert InvalidNumberOfDays(numberOfDays);
}
}
function validatePayment(SubscribableData storage self, uint256 numberOfDays, string memory promoDiscount) public view {
uint256 cost = calculateFee(self, numberOfDays, promoDiscount);
if (msg.value != cost) {
revert InvalidAmountForDays(numberOfDays, msg.value, cost);
}
}
function validateSubscription(SubscribableData storage self, uint256 numberOfDays, string calldata discountCode) public view {
validateDays(self,numberOfDays);
validatePayment(self,numberOfDays,discountCode);
}
function validateSubscription(SubscribableData storage self, uint256 numberOfDays) public view {
validateDays(self,numberOfDays);
validatePayment(self,numberOfDays,blank);
}
function floor(uint256 amount) public pure returns (uint256) {
return amount - (amount % 10000000000000000);
}
function expiresAt(SubscribableData storage self, uint256 tokenId) public view returns(uint256) {
return self.subscriptions[tokenId];
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "./Contractable.sol";
import "./FlexibleMetadata.sol";
import {SetSubscribable, SubscribableData, PromoDiscount, defaultPayable, InvalidNumberOfDays } from "./SetSubscribable.sol";
abstract contract Subscribable is Contractable {
using SetSubscribable for SubscribableData; // this is the crucial change
SubscribableData subs;
string constant blank = " ";
address payable internal OSM_TREASURY_WALLET = payable(defaultPayable);
constructor(string memory name, string memory symbol) FlexibleMetadata(name,symbol) {
subs.initialize();
}
function standardFee(uint256 numberOfDays) public view returns (uint256) {
return subs.calculateFee(numberOfDays);
}
function determineFee(uint256 numberOfDays, string memory discountCode) public view returns (uint256) {
return subs.calculateFee(numberOfDays,discountCode);
}
function determineCommission(uint256 amount, string memory discountCode) public view returns (uint256) {
return subs.calculateCommission(amount,discountCode);
}
function floor(uint256 amount) internal pure returns (uint256) {
return amount - (amount % 1000000000000000);
}
function expiresAt(uint256 tokenId) external view returns (uint256) {
return subs.expiresAt(tokenId);
}
function setRecipient(address recipient) external onlyOwner {
OSM_TREASURY_WALLET = payable(recipient);
}
function addPromoDiscount(string calldata discountCode, uint256 amount, uint256 commission, address partner) external onlyOwner {
subs.promoDiscounts[discountCode] = PromoDiscount(amount,commission,0,block.timestamp + (4 * 7 days),partner,true);
}
function getPromoDiscount(string calldata discountCode) external view returns (PromoDiscount memory) {
return subs.promoDiscounts[discountCode];
}
function setRateParams(uint256 multiplier, uint256 discount) external onlyOwner {
subs.setRateParams(multiplier,discount);
}
function commitSubscription(uint256 tokenId, uint numberOfDays) internal {
commitSubscription(tokenId, numberOfDays, blank);
}
function establishSubscription(uint256 tokenId, uint numberOfDays) internal {
subs.establishSubscription(tokenId, numberOfDays);
}
function commitSubscription(uint256 tokenId, uint numberOfDays, string memory discountCode) internal {
subs.validateSubscription(numberOfDays,discountCode);
subs.establishSubscription(tokenId,numberOfDays);
}
function renewSubscription(uint256 tokenId, uint numberOfDays, string memory discountCode) internal {
validateApprovedOrOwner(msg.sender, tokenId);
subs.validateSubscription(numberOfDays, discountCode);
commitSubscription(tokenId, numberOfDays, discountCode);
}
function isRenewable(uint256 tokenId) external view returns(bool) {
return exists(tokenId);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "./Subscribable.sol";
import "./LockableTransferrable.sol";
import { SetReceivable, ReceivableData, ReceivedTokenNonExistent, ReceivedTokenNonOwner, MintNotLive } from "./SetReceivable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/utils/Address.sol";
error ReceiverNotImplemented();
abstract contract TokenReceiver is Subscribable,IERC721Receiver {
using Address for address;
using SetReceivable for ReceivableData; // this is the crucial change
ReceivableData receivables;
function balanceOfWallet(address wallet, address contracted) public view returns (uint256) {
return receivables.balanceOfWallet(wallet,contracted);
}
function hasReceived(address wallet, address contracted) public view returns (uint256[] memory) {
return receivables.receivedFromWallet(wallet,contracted);
}
function _addTokenToReceivedEnumeration(address from, address contracted, uint256 tokenId) private {
receivables._addTokenToReceivedEnumeration(from,contracted,tokenId);
}
function _removeTokenFromReceivedEnumeration(address from, address contracted, uint256 tokenId) private {
receivables._removeTokenFromReceivedEnumeration(from,contracted,tokenId);
}
function tokenReceivedByIndex(address wallet, address contracted, uint256 index) public view returns (uint256) {
return receivables.tokenReceivedByIndex(wallet,contracted,index);
}
function withdraw(address contracted, uint256[] calldata tokenIds) public {
return receivables.withdraw(contracted,tokenIds);
}
function onERC721Received(address, address from, uint256 tokenId, bytes memory) public virtual override returns (bytes4) {
_addTokenToReceivedEnumeration(from, msg.sender, tokenId);
return this.onERC721Received.selector;
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
super.safeTransferFrom(from, to, tokenId, "");
receivables.swapOwner(from,to);
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
super.transferFrom(from, to, tokenId);
receivables.swapOwner(from,to);
}
}{
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {
"contracts/OSM/SetApprovable.sol": {
"SetApprovable": "0xd44fc4f2f36e6a75bca189001f2b243dbc7a0d12"
},
"contracts/OSM/SetContractable.sol": {
"SetContractable": "0x2008152272e4678d4661891125a070e4c3e5edc8"
},
"contracts/OSM/SetFlexibleMetadata.sol": {
"SetFlexibleMetadataData": "0xc4a3392eb009a88e9a8b4101587a1a7bcf804326"
},
"contracts/OSM/SetLockable.sol": {
"SetLockable": "0x1b7b48434d041eede56b532f2542ac3e1df42dba"
},
"contracts/OSM/SetOwnerEnumerable.sol": {
"SetOwnerEnumerable": "0xf7efe8f7f017b7eba93daab7c7518e6a4f90bf2e"
},
"contracts/OSM/SetReceivable.sol": {
"SetReceivable": "0x17e46924e6e004c5618bca34feb32c14d55fce51"
},
"contracts/OSM/SetSubscribable.sol": {
"SetSubscribable": "0xa1f273011d271ec06d35b7e731e7f899391cd9b0"
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"CallerIsNotOwner","type":"error"},{"inputs":[],"name":"ContractIsNot721Receiver","type":"error"},{"inputs":[{"internalType":"string","name":"discountCode","type":"string"}],"name":"DiscountIsInvalid","type":"error"},{"inputs":[],"name":"InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"zero","type":"address"}],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidTransferRecipient","type":"error"},{"inputs":[],"name":"MintIsNotLive","type":"error"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"name":"OnlyOneSubscriptionPerWallet","type":"error"},{"inputs":[],"name":"OwnerCannotBeZeroAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"TokenAlreadyMinted","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"TokenNonExistent","type":"error"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"TokenNonOwner","type":"error"},{"inputs":[],"name":"WalletLockedByOwner","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CommissionPaid","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":"string","name":"discountCode","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"commission","type":"uint256"},{"internalType":"address","name":"partner","type":"address"}],"name":"addPromoDiscount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"allowed","type":"address"},{"internalType":"string","name":"urlPath","type":"string"},{"internalType":"string","name":"erc","type":"string"},{"internalType":"uint256","name":"balanceRequired","type":"uint256"},{"internalType":"bool","name":"isStaking","type":"bool"},{"internalType":"bool","name":"isProxy","type":"bool"}],"name":"allowContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"allowances","outputs":[{"components":[{"internalType":"address","name":"addressed","type":"address"},{"internalType":"string","name":"urlPath","type":"string"},{"internalType":"string","name":"erc","type":"string"},{"internalType":"uint256","name":"balanceRequired","type":"uint256"},{"internalType":"bool","name":"isStaking","type":"bool"},{"internalType":"bool","name":"isProxy","type":"bool"},{"internalType":"bool","name":"exists","type":"bool"}],"internalType":"struct AllowedContract[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"balanceOfAllowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"address","name":"contracted","type":"address"}],"name":"balanceOfWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"custodianOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"discountCode","type":"string"}],"name":"determineCommission","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfDays","type":"uint256"},{"internalType":"string","name":"discountCode","type":"string"}],"name":"determineFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfDays","type":"uint256"},{"internalType":"string","name":"discountCode","type":"string"}],"name":"discountMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"expiresAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"discountCode","type":"string"}],"name":"getPromoDiscount","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"commission","type":"uint256"},{"internalType":"uint256","name":"timesUsed","type":"uint256"},{"internalType":"uint256","name":"expires","type":"uint256"},{"internalType":"address","name":"partner","type":"address"},{"internalType":"bool","name":"exists","type":"bool"}],"internalType":"struct PromoDiscount","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"address","name":"contracted","type":"address"}],"name":"hasReceived","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"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":"uint256","name":"id","type":"uint256"}],"name":"isLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isRenewable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"lockWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"lockedSince","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfDays","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"numberOfDays","type":"uint256"}],"name":"mintForRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","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":"string","name":"path","type":"string"}],"name":"pathAllows","outputs":[{"components":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"address","name":"wallet","type":"address"},{"internalType":"bool","name":"exists","type":"bool"}],"internalType":"struct AllowedPath","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numberOfDays","type":"uint256"},{"internalType":"string","name":"discountCode","type":"string"}],"name":"renewOSM","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numberOfDays","type":"uint256"}],"name":"renewOSM","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_reveal","type":"bool"}],"name":"reveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"revoked","type":"address"}],"name":"revokeContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"}],"name":"setContractUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"custodianAddress","type":"address"}],"name":"setCustodian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isLive","type":"bool"}],"name":"setMintLive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"multiplier","type":"uint256"},{"internalType":"uint256","name":"discount","type":"uint256"}],"name":"setRateParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"setRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"},{"internalType":"uint256","name":"tokenType","type":"uint256"}],"name":"setTokenUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfDays","type":"uint256"}],"name":"standardFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"address","name":"contracted","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenReceivedByIndex","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":[{"internalType":"address","name":"holder","type":"address"}],"name":"tokensOwnedBy","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unlockWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contracted","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6080604052735ae09f46967a92f3cf976e98f82b6fdd00784815602660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200006657600080fd5b50604051620063863803806200638683398181016040528101906200008c919062000396565b81818181620000a1336200013f60201b60201c565b8160079081620000b2919062000666565b508060089081620000c4919062000666565b505050601d73a1f273011d271ec06d35b7e731e7f899391cd9b0639bc21dba90916040518263ffffffff1660e01b815260040162000103919062000754565b60006040518083038186803b1580156200011c57600080fd5b505af415801562000131573d6000803e3d6000fd5b505050505050505062000771565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200026c8262000221565b810181811067ffffffffffffffff821117156200028e576200028d62000232565b5b80604052505050565b6000620002a362000203565b9050620002b1828262000261565b919050565b600067ffffffffffffffff821115620002d457620002d362000232565b5b620002df8262000221565b9050602081019050919050565b60005b838110156200030c578082015181840152602081019050620002ef565b60008484015250505050565b60006200032f6200032984620002b6565b62000297565b9050828152602081018484840111156200034e576200034d6200021c565b5b6200035b848285620002ec565b509392505050565b600082601f8301126200037b576200037a62000217565b5b81516200038d84826020860162000318565b91505092915050565b60008060408385031215620003b057620003af6200020d565b5b600083015167ffffffffffffffff811115620003d157620003d062000212565b5b620003df8582860162000363565b925050602083015167ffffffffffffffff81111562000403576200040262000212565b5b620004118582860162000363565b9150509250929050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200046e57607f821691505b60208210810362000484576200048362000426565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620004ee7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620004af565b620004fa8683620004af565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b600062000547620005416200053b8462000512565b6200051c565b62000512565b9050919050565b6000819050919050565b620005638362000526565b6200057b62000572826200054e565b848454620004bc565b825550505050565b600090565b6200059262000583565b6200059f81848462000558565b505050565b5b81811015620005c757620005bb60008262000588565b600181019050620005a5565b5050565b601f8211156200061657620005e0816200048a565b620005eb846200049f565b81016020851015620005fb578190505b620006136200060a856200049f565b830182620005a4565b50505b505050565b600082821c905092915050565b60006200063b600019846008026200061b565b1980831691505092915050565b600062000656838362000628565b9150826002028217905092915050565b62000671826200041b565b67ffffffffffffffff8111156200068d576200068c62000232565b5b62000699825462000455565b620006a6828285620005cb565b600060209050601f831160018114620006de5760008415620006c9578287015190505b620006d5858262000648565b86555062000745565b601f198416620006ee866200048a565b60005b828110156200071857848901518255600182019150602085019450602081019050620006f1565b8683101562000738578489015162000734601f89168262000628565b8355505b6001600288020188555050505b505050505050565b8082525050565b60006020820190506200076b60008301846200074d565b92915050565b615c0580620007816000396000f3fe60806040526004361061031a5760003560e01c8063937506f8116101ab578063c87b56dd116100f7578063de3efc9111610095578063ea66aeb31161006f578063ea66aeb314610c6d578063f2fde38b14610caa578063f6aacfb114610cd3578063fbd6a8af14610d105761031a565b8063de3efc9114610bc8578063e8a3d48514610c05578063e985e9c514610c305761031a565b8063cde317af116100d1578063cde317af14610b10578063cf41175914610b4d578063d480924d14610b76578063d6cd022e14610b9f5761031a565b8063c87b56dd14610a81578063cc2e3ee114610abe578063ccb4807b14610ae75761031a565b8063a2cd995d11610164578063af6f26cd1161013e578063af6f26cd146109b5578063b88d4fde146109f2578063ba4b62bf14610a1b578063bebd74ad14610a585761031a565b8063a2cd995d1461091f578063a9c133c71461095c578063ae38b5cf146109995761031a565b8063937506f81461080c578063940cd05b1461084957806395d89b4114610872578063a0712d681461089d578063a1a39af2146108b9578063a22cb465146108f65761031a565b806342842e0e1161026a57806370a08231116102235780638293744b116101fd5780638293744b1461075257806389cea3dd1461077b5780638da5cb5b146107b8578063911c9874146107e35761031a565b806370a08231146106c1578063715018a6146106fe57806380b9b855146107155761031a565b806342842e0e146105a357806353ca912a146105cc5780636264cc4e146105f55780636352211e146106325780636500d4111461066f5780636afc1334146106985761031a565b806318160ddd116102d75780632de409f3116102b15780632de409f3146104f857806335ca1c79146105355780633912928a1461055e5780633bbed4a01461057a5761031a565b806318160ddd1461046757806323b872dd146104925780632b603c71146104bb5761031a565b806301ffc9a71461031f57806306fdde031461035c578063081812fc14610387578063095ea7b3146103c4578063150b7a02146103ed57806317c957091461042a575b600080fd5b34801561032b57600080fd5b5061034660048036038101906103419190613bbc565b610d2c565b6040516103539190613c04565b60405180910390f35b34801561036857600080fd5b50610371610e0e565b60405161037e9190613caf565b60405180910390f35b34801561039357600080fd5b506103ae60048036038101906103a99190613d07565b610ea0565b6040516103bb9190613d75565b60405180910390f35b3480156103d057600080fd5b506103eb60048036038101906103e69190613dbc565b610eec565b005b3480156103f957600080fd5b50610414600480360381019061040f9190613f31565b610f03565b6040516104219190613fc3565b60405180910390f35b34801561043657600080fd5b50610451600480360381019061044c9190613d07565b610f22565b60405161045e9190613fed565b60405180910390f35b34801561047357600080fd5b5061047c610fa8565b6040516104899190613fed565b60405180910390f35b34801561049e57600080fd5b506104b960048036038101906104b49190614008565b610fb2565b005b3480156104c757600080fd5b506104e260048036038101906104dd919061405b565b611030565b6040516104ef9190614264565b60405180910390f35b34801561050457600080fd5b5061051f600480360381019061051a91906142e6565b6110bb565b60405161052c9190614432565b60405180910390f35b34801561054157600080fd5b5061055c60048036038101906105579190613d07565b61114f565b005b610578600480360381019061057391906144f5565b6111c6565b005b34801561058657600080fd5b506105a1600480360381019061059c919061405b565b6111e0565b005b3480156105af57600080fd5b506105ca60048036038101906105c59190614008565b61122c565b005b3480156105d857600080fd5b506105f360048036038101906105ee9190614590565b6112ba565b005b34801561060157600080fd5b5061061c60048036038101906106179190614008565b6112df565b6040516106299190613fed565b60405180910390f35b34801561063e57600080fd5b5061065960048036038101906106549190613d07565b61136b565b6040516106669190613d75565b60405180910390f35b34801561067b57600080fd5b50610696600480360381019061069191906145bd565b6113f1565b005b3480156106a457600080fd5b506106bf60048036038101906106ba9190613d07565b611475565b005b3480156106cd57600080fd5b506106e860048036038101906106e3919061405b565b6114fb565b6040516106f59190613fed565b60405180910390f35b34801561070a57600080fd5b50610713611553565b005b34801561072157600080fd5b5061073c6004803603810190610737919061468c565b611567565b6040516107499190613fed565b60405180910390f35b34801561075e57600080fd5b506107796004803603810190610774919061473e565b6115ef565b005b34801561078757600080fd5b506107a2600480360381019061079d919061405b565b611664565b6040516107af9190613fed565b60405180910390f35b3480156107c457600080fd5b506107cd6116ea565b6040516107da9190613d75565b60405180910390f35b3480156107ef57600080fd5b5061080a6004803603810190610805919061479e565b611713565b005b34801561081857600080fd5b50610833600480360381019061082e91906147de565b61178d565b6040516108409190613fed565b60405180910390f35b34801561085557600080fd5b50610870600480360381019061086b9190614590565b611816565b005b34801561087e57600080fd5b5061088761188d565b6040516108949190613caf565b60405180910390f35b6108b760048036038101906108b29190613d07565b61191f565b005b3480156108c557600080fd5b506108e060048036038101906108db9190613d07565b61196b565b6040516108ed9190613fed565b60405180910390f35b34801561090257600080fd5b5061091d6004803603810190610918919061481e565b6119c2565b005b34801561092b57600080fd5b50610946600480360381019061094191906142e6565b6119fc565b60405161095391906148d9565b60405180910390f35b34801561096857600080fd5b50610983600480360381019061097e91906147de565b611ad3565b60405161099091906149a3565b60405180910390f35b6109b360048036038101906109ae91906149c5565b611b61565b005b3480156109c157600080fd5b506109dc60048036038101906109d7919061468c565b611ba5565b6040516109e99190613fed565b60405180910390f35b3480156109fe57600080fd5b50610a196004803603810190610a149190613f31565b611c2e565b005b348015610a2757600080fd5b50610a426004803603810190610a3d9190613d07565b611c53565b604051610a4f9190613fed565b60405180910390f35b348015610a6457600080fd5b50610a7f6004803603810190610a7a9190614a05565b611cd9565b005b348015610a8d57600080fd5b50610aa86004803603810190610aa39190613d07565b611df2565b604051610ab59190613caf565b60405180910390f35b348015610aca57600080fd5b50610ae56004803603810190610ae0919061405b565b611e7d565b005b348015610af357600080fd5b50610b0e6004803603810190610b099190614a8d565b611eec565b005b348015610b1c57600080fd5b50610b376004803603810190610b329190613d07565b611f63565b604051610b449190613c04565b60405180910390f35b348015610b5957600080fd5b50610b746004803603810190610b6f9190613dbc565b611f75565b005b348015610b8257600080fd5b50610b9d6004803603810190610b989190614ad6565b611f93565b005b348015610bab57600080fd5b50610bc66004803603810190610bc191906149c5565b6120f7565b005b348015610bd457600080fd5b50610bef6004803603810190610bea9190613d07565b612171565b604051610bfc9190613d75565b60405180910390f35b348015610c1157600080fd5b50610c1a6121ff565b604051610c279190613caf565b60405180910390f35b348015610c3c57600080fd5b50610c576004803603810190610c5291906147de565b612286565b604051610c649190613c04565b60405180910390f35b348015610c7957600080fd5b50610c946004803603810190610c8f919061405b565b61230f565b604051610ca191906149a3565b60405180910390f35b348015610cb657600080fd5b50610cd16004803603810190610ccc919061405b565b6123e4565b005b348015610cdf57600080fd5b50610cfa6004803603810190610cf59190613d07565b61245e565b604051610d079190613c04565b60405180910390f35b610d2a6004803603810190610d259190614b32565b6124c2565b005b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610df757507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610e075750610e068261266a565b5b9050919050565b606060078054610e1d90614bc1565b80601f0160208091040260200160405190810160405280929190818152602001828054610e4990614bc1565b8015610e965780601f10610e6b57610100808354040283529160200191610e96565b820191906000526020600020905b815481529060010190602001808311610e7957829003601f168201915b5050505050905090565b6000610eab826126d4565b600d600601600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610ef581612721565b610eff8282612764565b5050565b6000610f108433856128b3565b63150b7a0260e01b9050949350505050565b6000601d73a1f273011d271ec06d35b7e731e7f899391cd9b06347f5a81c9091846040518363ffffffff1660e01b8152600401610f60929190614c08565b602060405180830381865af4158015610f7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa19190614c46565b9050919050565b6000601854905090565b610fbd838383612928565b60277317e46924e6e004c5618bca34feb32c14d55fce51636e520c42909185856040518463ffffffff1660e01b8152600401610ffb93929190614c89565b60006040518083038186803b15801561101357600080fd5b505af4158015611027573d6000803e3d6000fd5b50505050505050565b60606019732008152272e4678d4661891125a070e4c3e5edc86308ce42cc9091846040518363ffffffff1660e01b815260040161106e929190614cc7565b600060405180830381865af415801561108b573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906110b49190614f61565b9050919050565b6110c3613a22565b6019732008152272e4678d4661891125a070e4c3e5edc863fd16883c909185856040518463ffffffff1660e01b815260040161110193929190614fe8565b600060405180830381865af415801561111e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611147919061515d565b905092915050565b6015731b7b48434d041eede56b532f2542ac3e1df42dba638fb14e3b90916111768461136b565b6040518363ffffffff1660e01b81526004016111939291906151ad565b60006040518083038186803b1580156111ab57600080fd5b505af41580156111bf573d6000803e3d6000fd5b5050505050565b6111d0828261294b565b6111db838383612b52565b505050565b6111e8612bda565b80602660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61124783838360405180602001604052806000815250611c2e565b60277317e46924e6e004c5618bca34feb32c14d55fce51636e520c42909185856040518463ffffffff1660e01b815260040161128593929190614c89565b60006040518083038186803b15801561129d57600080fd5b505af41580156112b1573d6000803e3d6000fd5b50505050505050565b6112c2612bda565b80601760006101000a81548160ff02191690831515021790555050565b600060277317e46924e6e004c5618bca34feb32c14d55fce51635908f8e590918686866040518563ffffffff1660e01b815260040161132194939291906151d6565b602060405180830381865af415801561133e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113629190614c46565b90509392505050565b6000600973f7efe8f7f017b7eba93daab7c7518e6a4f90bf2e630266c7a39091846040518363ffffffff1660e01b81526004016113a9929190615222565b602060405180830381865af41580156113c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ea919061524b565b9050919050565b6019732008152272e4678d4661891125a070e4c3e5edc8639895d47d90918a8a8a8a8a8a8a8a6040518a63ffffffff1660e01b815260040161143b99989796959493929190615287565b60006040518083038186803b15801561145357600080fd5b505af4158015611467573d6000803e3d6000fd5b505050505050505050505050565b60006114808261136b565b905061148b81612c53565b6015731b7b48434d041eede56b532f2542ac3e1df42dba63b04686629091836040518363ffffffff1660e01b81526004016114c79291906151ad565b60006040518083038186803b1580156114df57600080fd5b505af41580156114f3573d6000803e3d6000fd5b505050505050565b600061150682612ccc565b600960010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b61155b612bda565b6115656000612d35565b565b6000601d73a1f273011d271ec06d35b7e731e7f899391cd9b0629c1dd4909185856040518463ffffffff1660e01b81526004016115a693929190615341565b602060405180830381865af41580156115c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115e79190614c46565b905092915050565b60277317e46924e6e004c5618bca34feb32c14d55fce51634412be0090918585856040518563ffffffff1660e01b815260040161162f94939291906153fa565b60006040518083038186803b15801561164757600080fd5b505af415801561165b573d6000803e3d6000fd5b50505050505050565b60006019732008152272e4678d4661891125a070e4c3e5edc86373632d479091846040518363ffffffff1660e01b81526004016116a2929190614cc7565b602060405180830381865af41580156116bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e39190614c46565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6015731b7b48434d041eede56b532f2542ac3e1df42dba6311841d7090918361173b8661136b565b6040518463ffffffff1660e01b81526004016117599392919061543a565b60006040518083038186803b15801561177157600080fd5b505af4158015611785573d6000803e3d6000fd5b505050505050565b600060277317e46924e6e004c5618bca34feb32c14d55fce5163c412a736909185856040518463ffffffff1660e01b81526004016117cd93929190614c89565b602060405180830381865af41580156117ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180e9190614c46565b905092915050565b61181e612bda565b600173c4a3392eb009a88e9a8b4101587a1a7bcf80432663da1542a69091836040518363ffffffff1660e01b815260040161185a929190615478565b60006040518083038186803b15801561187257600080fd5b505af4158015611886573d6000803e3d6000fd5b5050505050565b60606008805461189c90614bc1565b80601f01602080910402602001604051908101604052809291908181526020018280546118c890614bc1565b80156119155780601f106118ea57610100808354040283529160200191611915565b820191906000526020600020905b8154815290600101906020018083116118f857829003601f168201915b5050505050905090565b61195e816040518060400160405280600181526020017f200000000000000000000000000000000000000000000000000000000000000081525061294b565b6119683382612df9565b50565b60006015600101600061197d8461136b565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101549050919050565b6119ee6119ce3361230f565b6000815181106119e1576119e06154a1565b5b6020026020010151612721565b6119f88282612e3d565b5050565b611a04613a5b565b601d6001018383604051611a19929190615500565b90815260200160405180910390206040518060c0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016004820160149054906101000a900460ff161515151581525050905092915050565b606060277317e46924e6e004c5618bca34feb32c14d55fce5163c680a5c1909185856040518463ffffffff1660e01b8152600401611b1393929190614c89565b600060405180830381865af4158015611b30573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611b5991906155dc565b905092915050565b611ba182826040518060400160405280600181526020017f20000000000000000000000000000000000000000000000000000000000000008152506111c6565b5050565b6000601d73a1f273011d271ec06d35b7e731e7f899391cd9b063967cf8d1909185856040518463ffffffff1660e01b8152600401611be593929190615341565b602060405180830381865af4158015611c02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c269190614c46565b905092915050565b611c383383612f27565b611c4182612721565b611c4d8484848461306e565b50505050565b6000601d73a1f273011d271ec06d35b7e731e7f899391cd9b063db48b3009091846040518363ffffffff1660e01b8152600401611c91929190614c08565b602060405180830381865af4158015611cae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd29190614c46565b9050919050565b611ce1612bda565b6040518060c00160405280848152602001838152602001600081526020016224ea0042611d0e9190615654565b81526020018273ffffffffffffffffffffffffffffffffffffffff16815260200160011515815250601d6001018686604051611d4b929190615500565b90815260200160405180910390206000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160040160146101000a81548160ff0219169083151502179055509050505050505050565b6060600173c4a3392eb009a88e9a8b4101587a1a7bcf80432663d30eae479091846040518363ffffffff1660e01b8152600401611e30929190615688565b600060405180830381865af4158015611e4d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611e7691906156b1565b9050919050565b6019732008152272e4678d4661891125a070e4c3e5edc863b81093009091836040518363ffffffff1660e01b8152600401611eb9929190614cc7565b60006040518083038186803b158015611ed157600080fd5b505af4158015611ee5573d6000803e3d6000fd5b5050505050565b611ef4612bda565b600173c4a3392eb009a88e9a8b4101587a1a7bcf804326632d5459e29091836040518363ffffffff1660e01b8152600401611f309291906156fa565b60006040518083038186803b158015611f4857600080fd5b505af4158015611f5c573d6000803e3d6000fd5b5050505050565b6000611f6e826130c1565b9050919050565b611f7d612bda565b611f8f611f89836130f1565b8261311d565b5050565b6002810361200c57600173c4a3392eb009a88e9a8b4101587a1a7bcf80432663db6a3cab9091846040518363ffffffff1660e01b8152600401611fd79291906156fa565b60006040518083038186803b158015611fef57600080fd5b505af4158015612003573d6000803e3d6000fd5b505050506120f3565b6003810361208557600173c4a3392eb009a88e9a8b4101587a1a7bcf8043266348b5a5a39091846040518363ffffffff1660e01b81526004016120509291906156fa565b60006040518083038186803b15801561206857600080fd5b505af415801561207c573d6000803e3d6000fd5b505050506120f2565b600173c4a3392eb009a88e9a8b4101587a1a7bcf804326638bebb5869091846040518363ffffffff1660e01b81526004016120c19291906156fa565b60006040518083038186803b1580156120d957600080fd5b505af41580156120ed573d6000803e3d6000fd5b505050505b5b5050565b6120ff612bda565b601d73a1f273011d271ec06d35b7e731e7f899391cd9b0637ca5f858909184846040518463ffffffff1660e01b815260040161213d9392919061572a565b60006040518083038186803b15801561215557600080fd5b505af4158015612169573d6000803e3d6000fd5b505050505050565b60006015731b7b48434d041eede56b532f2542ac3e1df42dba63f1650c05909161219a8561136b565b6040518363ffffffff1660e01b81526004016121b79291906151ad565b602060405180830381865af41580156121d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f8919061524b565b9050919050565b6060600173c4a3392eb009a88e9a8b4101587a1a7bcf804326636ae383de90916040518263ffffffff1660e01b815260040161223b9190615761565b600060405180830381865af4158015612258573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061228191906156b1565b905090565b6000600d73d44fc4f2f36e6a75bca189001f2b243dbc7a0d1263e4e0a723909185856040518463ffffffff1660e01b81526004016122c693929190615783565b602060405180830381865af41580156122e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230791906157ba565b905092915050565b6060600973f7efe8f7f017b7eba93daab7c7518e6a4f90bf2e6303c242519091846040518363ffffffff1660e01b815260040161234d9291906157e7565b602060405180830381865af415801561236a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238e9190615846565b8054806020026020016040519081016040528092919081815260200182805480156123d857602002820191906000526020600020905b8154815260200190600101908083116123c4575b50505050509050919050565b6123ec612bda565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612452576040517fc81abf6000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61245b81612d35565b50565b6000601560010160006124708461136b565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b601d60010182826040516124d7929190615500565b908152602001604051809103902060040160149054906101000a900460ff161580612527575042601d6001018383604051612513929190615500565b908152602001604051809103902060030154105b1561256b5781816040517f06dac5070000000000000000000000000000000000000000000000000000000081526004016125629291906158a0565b60405180910390fd5b6125b98383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061294b565b6001601d60010183836040516125d0929190615500565b9081526020016040518091039020600201546125ec9190615654565b601d6001018383604051612601929190615500565b908152602001604051809103902060020181905550612665338484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061318f565b505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6126dd816130c1565b61271e57806040517f3d2f7ef60000000000000000000000000000000000000000000000000000000081526004016127159190613fed565b60405180910390fd5b50565b61272a8161245e565b15612761576040517f35857a7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b3373ffffffffffffffffffffffffffffffffffffffff166127848261136b565b73ffffffffffffffffffffffffffffffffffffffff16146127de5733816040517fa52847350000000000000000000000000000000000000000000000000000000081526004016127d59291906158c4565b60405180910390fd5b600d73d44fc4f2f36e6a75bca189001f2b243dbc7a0d1263735b7846909184846040518463ffffffff1660e01b815260040161281c939291906158ed565b60006040518083038186803b15801561283457600080fd5b505af4158015612848573d6000803e3d6000fd5b50505050808273ffffffffffffffffffffffffffffffffffffffff1661286d8361136b565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60277317e46924e6e004c5618bca34feb32c14d55fce5163284800ce90918585856040518563ffffffff1660e01b81526004016128f394939291906151d6565b60006040518083038186803b15801561290b57600080fd5b505af415801561291f573d6000803e3d6000fd5b50505050505050565b6129323382612f27565b61293b81612721565b6129468383836131a7565b505050565b60006129578383611567565b90506000601d6001018360405161296e9190615955565b908152602001604051809103902060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060006129ae8385611ba5565b90506000811115612a7e578173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156129ff573d6000803e3d6000fd5b507f885e6f6235626292940f78c947a331f4c7c1d7f50a48b38092cf546bc9c7907a601d60010185604051612a349190615955565b908152602001604051809103902060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682604051612a759291906158c4565b60405180910390a15b602660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc8285612ac6919061596c565b9081150290604051600060405180830381858888f19350505050158015612af1573d6000803e3d6000fd5b506001601d60010185604051612b079190615955565b908152602001604051809103902060020154612b239190615654565b601d60010185604051612b369190615955565b9081526020016040518091039020600201819055505050505050565b612b5c3384612f27565b601d73a1f273011d271ec06d35b7e731e7f899391cd9b063befc0ab6909184846040518463ffffffff1660e01b8152600401612b9a93929190615341565b60006040518083038186803b158015612bb257600080fd5b505af4158015612bc6573d6000803e3d6000fd5b50505050612bd5838383613287565b505050565b3373ffffffffffffffffffffffffffffffffffffffff16612bf96116ea565b73ffffffffffffffffffffffffffffffffffffffff1614612c5157336040517fd4ed9a17000000000000000000000000000000000000000000000000000000008152600401612c489190613d75565b60405180910390fd5b565b600d73d44fc4f2f36e6a75bca189001f2b243dbc7a0d12633f4e7cce909183612c7b8561230f565b6040518463ffffffff1660e01b8152600401612c9993929190615a25565b60006040518083038186803b158015612cb157600080fd5b505af4158015612cc5573d6000803e3d6000fd5b5050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612d32576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b612e3982826040518060400160405280600181526020017f200000000000000000000000000000000000000000000000000000000000000081525061318f565b5050565b8015612eb457600d73d44fc4f2f36e6a75bca189001f2b243dbc7a0d1263b2875b199091846040518363ffffffff1660e01b8152600401612e7f929190615a63565b60006040518083038186803b158015612e9757600080fd5b505af4158015612eab573d6000803e3d6000fd5b50505050612f23565b600d73d44fc4f2f36e6a75bca189001f2b243dbc7a0d12630aeeeecb909184336040518463ffffffff1660e01b8152600401612ef293929190615783565b60006040518083038186803b158015612f0a57600080fd5b505af4158015612f1e573d6000803e3d6000fd5b505050505b5050565b6000612f328261136b565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161480612f745750612f738184612286565b5b8061302657508273ffffffffffffffffffffffffffffffffffffffff16600d73d44fc4f2f36e6a75bca189001f2b243dbc7a0d1263dc6cf67e9091856040518363ffffffff1660e01b8152600401612fcd929190615a8c565b602060405180830381865af4158015612fea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061300e919061524b565b73ffffffffffffffffffffffffffffffffffffffff16145b6130695782826040517fa52847350000000000000000000000000000000000000000000000000000000081526004016130609291906158c4565b60405180910390fd5b505050565b61307a84848484613368565b6130b0576040517fe0c7635200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6130bb8484846131a7565b50505050565b6000600d600601600083815260200190815260200160002060000160149054906101000a900460ff169050919050565b60008060016130fe610fa8565b6131089190615654565b905061311483826134df565b80915050919050565b601d73a1f273011d271ec06d35b7e731e7f899391cd9b063a253d058909184846040518463ffffffff1660e01b815260040161315b9392919061572a565b60006040518083038186803b15801561317357600080fd5b505af4158015613187573d6000803e3d6000fd5b505050505050565b6131a261319b846130f1565b8383613287565b505050565b60006131b2836114fb565b11156131fd576131c1826114fb565b6040517f8b03eb030000000000000000000000000000000000000000000000000000000081526004016131f49190613fed565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613263576040517f9b7cfcb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61326c81613615565b613277838383613684565b6132828383836137d3565b505050565b601d73a1f273011d271ec06d35b7e731e7f899391cd9b063befc0ab6909184846040518463ffffffff1660e01b81526004016132c593929190615341565b60006040518083038186803b1580156132dd57600080fd5b505af41580156132f1573d6000803e3d6000fd5b50505050601d73a1f273011d271ec06d35b7e731e7f899391cd9b063a253d058909185856040518463ffffffff1660e01b81526004016133339392919061572a565b60006040518083038186803b15801561334b57600080fd5b505af415801561335f573d6000803e3d6000fd5b50505050505050565b60006133898473ffffffffffffffffffffffffffffffffffffffff1661388b565b156134d2578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02338786866040518563ffffffff1660e01b81526004016133cd9493929190615b0a565b6020604051808303816000875af192505050801561340957506040513d601f19601f820116820180604052508101906134069190615b6b565b60015b613482573d8060008114613439576040519150601f19603f3d011682016040523d82523d6000602084013e61343e565b606091505b50600081510361347a576040517f9b7cfcb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149150506134d7565b600190505b949350505050565b601760009054906101000a900460ff16613525576040517f03eaac9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361359657816040517f17858bbe00000000000000000000000000000000000000000000000000000000815260040161358d9190613d75565b60405180910390fd5b61359f816130c1565b156135e157806040517f8b474e540000000000000000000000000000000000000000000000000000000081526004016135d89190613fed565b60405180910390fd5b6001601860008282546135f49190615654565b9250508190555061360582826138ae565b613611600083836137d3565b5050565b600d73d44fc4f2f36e6a75bca189001f2b243dbc7a0d1263ad8e62069091836040518363ffffffff1660e01b8152600401613651929190615a8c565b60006040518083038186803b15801561366957600080fd5b505af415801561367d573d6000803e3d6000fd5b5050505050565b600973f7efe8f7f017b7eba93daab7c7518e6a4f90bf2e63a0576ba2909185846040518463ffffffff1660e01b81526004016136c293929190615b98565b60006040518083038186803b1580156136da57600080fd5b505af41580156136ee573d6000803e3d6000fd5b50505050600973f7efe8f7f017b7eba93daab7c7518e6a4f90bf2e63a0576ba2909185846040518463ffffffff1660e01b815260040161373093929190615b98565b60006040518083038186803b15801561374857600080fd5b505af415801561375c573d6000803e3d6000fd5b50505050600973f7efe8f7f017b7eba93daab7c7518e6a4f90bf2e63c213e42f909184846040518463ffffffff1660e01b815260040161379e93929190615b98565b60006040518083038186803b1580156137b657600080fd5b505af41580156137ca573d6000803e3d6000fd5b50505050505050565b808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46060613885836040518060c0016040528060001515815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200184815260200160011515815250613920565b50505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600973f7efe8f7f017b7eba93daab7c7518e6a4f90bf2e63c213e42f909184846040518463ffffffff1660e01b81526004016138ec93929190615b98565b60006040518083038186803b15801561390457600080fd5b505af4158015613918573d6000803e3d6000fd5b505050505050565b80601560010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506060820151816003015560808201518160040190805190602001906139fa929190613aa9565b5060a08201518160050160006101000a81548160ff0219169083151502179055509050505050565b604051806060016040528060608152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000151581525090565b6040518060c0016040528060008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000151581525090565b828054828255906000526020600020908101928215613b22579160200282015b82811115613b215782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190613ac9565b5b509050613b2f9190613b33565b5090565b5b80821115613b4c576000816000905550600101613b34565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613b9981613b64565b8114613ba457600080fd5b50565b600081359050613bb681613b90565b92915050565b600060208284031215613bd257613bd1613b5a565b5b6000613be084828501613ba7565b91505092915050565b60008115159050919050565b613bfe81613be9565b82525050565b6000602082019050613c196000830184613bf5565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613c59578082015181840152602081019050613c3e565b60008484015250505050565b6000601f19601f8301169050919050565b6000613c8182613c1f565b613c8b8185613c2a565b9350613c9b818560208601613c3b565b613ca481613c65565b840191505092915050565b60006020820190508181036000830152613cc98184613c76565b905092915050565b6000819050919050565b613ce481613cd1565b8114613cef57600080fd5b50565b600081359050613d0181613cdb565b92915050565b600060208284031215613d1d57613d1c613b5a565b5b6000613d2b84828501613cf2565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613d5f82613d34565b9050919050565b613d6f81613d54565b82525050565b6000602082019050613d8a6000830184613d66565b92915050565b613d9981613d54565b8114613da457600080fd5b50565b600081359050613db681613d90565b92915050565b60008060408385031215613dd357613dd2613b5a565b5b6000613de185828601613da7565b9250506020613df285828601613cf2565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613e3e82613c65565b810181811067ffffffffffffffff82111715613e5d57613e5c613e06565b5b80604052505050565b6000613e70613b50565b9050613e7c8282613e35565b919050565b600067ffffffffffffffff821115613e9c57613e9b613e06565b5b613ea582613c65565b9050602081019050919050565b82818337600083830152505050565b6000613ed4613ecf84613e81565b613e66565b905082815260208101848484011115613ef057613eef613e01565b5b613efb848285613eb2565b509392505050565b600082601f830112613f1857613f17613dfc565b5b8135613f28848260208601613ec1565b91505092915050565b60008060008060808587031215613f4b57613f4a613b5a565b5b6000613f5987828801613da7565b9450506020613f6a87828801613da7565b9350506040613f7b87828801613cf2565b925050606085013567ffffffffffffffff811115613f9c57613f9b613b5f565b5b613fa887828801613f03565b91505092959194509250565b613fbd81613b64565b82525050565b6000602082019050613fd86000830184613fb4565b92915050565b613fe781613cd1565b82525050565b60006020820190506140026000830184613fde565b92915050565b60008060006060848603121561402157614020613b5a565b5b600061402f86828701613da7565b935050602061404086828701613da7565b925050604061405186828701613cf2565b9150509250925092565b60006020828403121561407157614070613b5a565b5b600061407f84828501613da7565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6140bd81613d54565b82525050565b600082825260208201905092915050565b60006140df82613c1f565b6140e981856140c3565b93506140f9818560208601613c3b565b61410281613c65565b840191505092915050565b61411681613cd1565b82525050565b61412581613be9565b82525050565b600060e08301600083015161414360008601826140b4565b506020830151848203602086015261415b82826140d4565b9150506040830151848203604086015261417582826140d4565b915050606083015161418a606086018261410d565b50608083015161419d608086018261411c565b5060a08301516141b060a086018261411c565b5060c08301516141c360c086018261411c565b508091505092915050565b60006141da838361412b565b905092915050565b6000602082019050919050565b60006141fa82614088565b6142048185614093565b935083602082028501614216856140a4565b8060005b85811015614252578484038952815161423385826141ce565b945061423e836141e2565b925060208a0199505060018101905061421a565b50829750879550505050505092915050565b6000602082019050818103600083015261427e81846141ef565b905092915050565b600080fd5b600080fd5b60008083601f8401126142a6576142a5613dfc565b5b8235905067ffffffffffffffff8111156142c3576142c2614286565b5b6020830191508360018202830111156142df576142de61428b565b5b9250929050565b600080602083850312156142fd576142fc613b5a565b5b600083013567ffffffffffffffff81111561431b5761431a613b5f565b5b61432785828601614290565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061436b83836140b4565b60208301905092915050565b6000602082019050919050565b600061438f82614333565b614399818561433e565b93506143a48361434f565b8060005b838110156143d55781516143bc888261435f565b97506143c783614377565b9250506001810190506143a8565b5085935050505092915050565b600060608301600083015184820360008601526143ff8282614384565b915050602083015161441460208601826140b4565b506040830151614427604086018261411c565b508091505092915050565b6000602082019050818103600083015261444c81846143e2565b905092915050565b600067ffffffffffffffff82111561446f5761446e613e06565b5b61447882613c65565b9050602081019050919050565b600061449861449384614454565b613e66565b9050828152602081018484840111156144b4576144b3613e01565b5b6144bf848285613eb2565b509392505050565b600082601f8301126144dc576144db613dfc565b5b81356144ec848260208601614485565b91505092915050565b60008060006060848603121561450e5761450d613b5a565b5b600061451c86828701613cf2565b935050602061452d86828701613cf2565b925050604084013567ffffffffffffffff81111561454e5761454d613b5f565b5b61455a868287016144c7565b9150509250925092565b61456d81613be9565b811461457857600080fd5b50565b60008135905061458a81614564565b92915050565b6000602082840312156145a6576145a5613b5a565b5b60006145b48482850161457b565b91505092915050565b60008060008060008060008060c0898b0312156145dd576145dc613b5a565b5b60006145eb8b828c01613da7565b985050602089013567ffffffffffffffff81111561460c5761460b613b5f565b5b6146188b828c01614290565b9750975050604089013567ffffffffffffffff81111561463b5761463a613b5f565b5b6146478b828c01614290565b9550955050606061465a8b828c01613cf2565b935050608061466b8b828c0161457b565b92505060a061467c8b828c0161457b565b9150509295985092959890939650565b600080604083850312156146a3576146a2613b5a565b5b60006146b185828601613cf2565b925050602083013567ffffffffffffffff8111156146d2576146d1613b5f565b5b6146de858286016144c7565b9150509250929050565b60008083601f8401126146fe576146fd613dfc565b5b8235905067ffffffffffffffff81111561471b5761471a614286565b5b6020830191508360208202830111156147375761473661428b565b5b9250929050565b60008060006040848603121561475757614756613b5a565b5b600061476586828701613da7565b935050602084013567ffffffffffffffff81111561478657614785613b5f565b5b614792868287016146e8565b92509250509250925092565b600080604083850312156147b5576147b4613b5a565b5b60006147c385828601613cf2565b92505060206147d485828601613da7565b9150509250929050565b600080604083850312156147f5576147f4613b5a565b5b600061480385828601613da7565b925050602061481485828601613da7565b9150509250929050565b6000806040838503121561483557614834613b5a565b5b600061484385828601613da7565b92505060206148548582860161457b565b9150509250929050565b60c082016000820151614874600085018261410d565b506020820151614887602085018261410d565b50604082015161489a604085018261410d565b5060608201516148ad606085018261410d565b5060808201516148c060808501826140b4565b5060a08201516148d360a085018261411c565b50505050565b600060c0820190506148ee600083018461485e565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061492c838361410d565b60208301905092915050565b6000602082019050919050565b6000614950826148f4565b61495a81856148ff565b935061496583614910565b8060005b8381101561499657815161497d8882614920565b975061498883614938565b925050600181019050614969565b5085935050505092915050565b600060208201905081810360008301526149bd8184614945565b905092915050565b600080604083850312156149dc576149db613b5a565b5b60006149ea85828601613cf2565b92505060206149fb85828601613cf2565b9150509250929050565b600080600080600060808688031215614a2157614a20613b5a565b5b600086013567ffffffffffffffff811115614a3f57614a3e613b5f565b5b614a4b88828901614290565b95509550506020614a5e88828901613cf2565b9350506040614a6f88828901613cf2565b9250506060614a8088828901613da7565b9150509295509295909350565b600060208284031215614aa357614aa2613b5a565b5b600082013567ffffffffffffffff811115614ac157614ac0613b5f565b5b614acd848285016144c7565b91505092915050565b60008060408385031215614aed57614aec613b5a565b5b600083013567ffffffffffffffff811115614b0b57614b0a613b5f565b5b614b17858286016144c7565b9250506020614b2885828601613cf2565b9150509250929050565b600080600060408486031215614b4b57614b4a613b5a565b5b6000614b5986828701613cf2565b935050602084013567ffffffffffffffff811115614b7a57614b79613b5f565b5b614b8686828701614290565b92509250509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614bd957607f821691505b602082108103614bec57614beb614b92565b5b50919050565b8082525050565b614c0281613cd1565b82525050565b6000604082019050614c1d6000830185614bf2565b614c2a6020830184614bf9565b9392505050565b600081519050614c4081613cdb565b92915050565b600060208284031215614c5c57614c5b613b5a565b5b6000614c6a84828501614c31565b91505092915050565b8082525050565b614c8381613d54565b82525050565b6000606082019050614c9e6000830186614c73565b614cab6020830185614c7a565b614cb86040830184614c7a565b949350505050565b8082525050565b6000604082019050614cdc6000830185614cc0565b614ce96020830184614c7a565b9392505050565b600067ffffffffffffffff821115614d0b57614d0a613e06565b5b602082029050602081019050919050565b600080fd5b600080fd5b600081519050614d3581613d90565b92915050565b6000614d4e614d4984614454565b613e66565b905082815260208101848484011115614d6a57614d69613e01565b5b614d75848285613c3b565b509392505050565b600082601f830112614d9257614d91613dfc565b5b8151614da2848260208601614d3b565b91505092915050565b600081519050614dba81614564565b92915050565b600060e08284031215614dd657614dd5614d1c565b5b614de060e0613e66565b90506000614df084828501614d26565b600083015250602082015167ffffffffffffffff811115614e1457614e13614d21565b5b614e2084828501614d7d565b602083015250604082015167ffffffffffffffff811115614e4457614e43614d21565b5b614e5084828501614d7d565b6040830152506060614e6484828501614c31565b6060830152506080614e7884828501614dab565b60808301525060a0614e8c84828501614dab565b60a08301525060c0614ea084828501614dab565b60c08301525092915050565b6000614ebf614eba84614cf0565b613e66565b90508083825260208201905060208402830185811115614ee257614ee161428b565b5b835b81811015614f2957805167ffffffffffffffff811115614f0757614f06613dfc565b5b808601614f148982614dc0565b85526020850194505050602081019050614ee4565b5050509392505050565b600082601f830112614f4857614f47613dfc565b5b8151614f58848260208601614eac565b91505092915050565b600060208284031215614f7757614f76613b5a565b5b600082015167ffffffffffffffff811115614f9557614f94613b5f565b5b614fa184828501614f33565b91505092915050565b600082825260208201905092915050565b6000614fc78385614faa565b9350614fd4838584613eb2565b614fdd83613c65565b840190509392505050565b6000604082019050614ffd6000830186614cc0565b8181036020830152615010818486614fbb565b9050949350505050565b600067ffffffffffffffff82111561503557615034613e06565b5b602082029050602081019050919050565b60006150596150548461501a565b613e66565b9050808382526020820190506020840283018581111561507c5761507b61428b565b5b835b818110156150a557806150918882614d26565b84526020840193505060208101905061507e565b5050509392505050565b600082601f8301126150c4576150c3613dfc565b5b81516150d4848260208601615046565b91505092915050565b6000606082840312156150f3576150f2614d1c565b5b6150fd6060613e66565b9050600082015167ffffffffffffffff81111561511d5761511c614d21565b5b615129848285016150af565b600083015250602061513d84828501614d26565b602083015250604061515184828501614dab565b60408301525092915050565b60006020828403121561517357615172613b5a565b5b600082015167ffffffffffffffff81111561519157615190613b5f565b5b61519d848285016150dd565b91505092915050565b8082525050565b60006040820190506151c260008301856151a6565b6151cf6020830184614c7a565b9392505050565b60006080820190506151eb6000830187614c73565b6151f86020830186614c7a565b6152056040830185614c7a565b6152126060830184614bf9565b95945050505050565b8082525050565b6000604082019050615237600083018561521b565b6152446020830184614bf9565b9392505050565b60006020828403121561526157615260613b5a565b5b600061526f84828501614d26565b91505092915050565b61528181613be9565b82525050565b600060e08201905061529c600083018c614cc0565b6152a9602083018b614c7a565b81810360408301526152bc81898b614fbb565b905081810360608301526152d1818789614fbb565b90506152e06080830186614bf9565b6152ed60a0830185615278565b6152fa60c0830184615278565b9a9950505050505050505050565b600061531382613c1f565b61531d8185614faa565b935061532d818560208601613c3b565b61533681613c65565b840191505092915050565b60006060820190506153566000830186614bf2565b6153636020830185614bf9565b81810360408301526153758184615308565b9050949350505050565b600082825260208201905092915050565b600080fd5b82818337505050565b60006153aa838561537f565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156153dd576153dc615390565b5b6020830292506153ee838584615395565b82840190509392505050565b600060608201905061540f6000830187614c73565b61541c6020830186614c7a565b818103604083015261542f81848661539e565b905095945050505050565b600060608201905061544f60008301866151a6565b61545c6020830185614c7a565b6154696040830184614c7a565b949350505050565b8082525050565b600060408201905061548d6000830185615471565b61549a6020830184615278565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081905092915050565b60006154e783856154d0565b93506154f4838584613eb2565b82840190509392505050565b600061550d8284866154db565b91508190509392505050565b600067ffffffffffffffff82111561553457615533613e06565b5b602082029050602081019050919050565b600061555861555384615519565b613e66565b9050808382526020820190506020840283018581111561557b5761557a61428b565b5b835b818110156155a457806155908882614c31565b84526020840193505060208101905061557d565b5050509392505050565b600082601f8301126155c3576155c2613dfc565b5b81516155d3848260208601615545565b91505092915050565b6000602082840312156155f2576155f1613b5a565b5b600082015167ffffffffffffffff8111156156105761560f613b5f565b5b61561c848285016155ae565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061565f82613cd1565b915061566a83613cd1565b925082820190508082111561568257615681615625565b5b92915050565b600060408201905061569d6000830185615471565b6156aa6020830184614bf9565b9392505050565b6000602082840312156156c7576156c6613b5a565b5b600082015167ffffffffffffffff8111156156e5576156e4613b5f565b5b6156f184828501614d7d565b91505092915050565b600060408201905061570f6000830185615471565b81810360208301526157218184615308565b90509392505050565b600060608201905061573f6000830186614bf2565b61574c6020830185614bf9565b6157596040830184614bf9565b949350505050565b60006020820190506157766000830184615471565b92915050565b8082525050565b6000606082019050615798600083018661577c565b6157a56020830185614c7a565b6157b26040830184614c7a565b949350505050565b6000602082840312156157d0576157cf613b5a565b5b60006157de84828501614dab565b91505092915050565b60006040820190506157fc600083018561521b565b6158096020830184614c7a565b9392505050565b6000819050919050565b61582381615810565b811461582e57600080fd5b50565b6000815190506158408161581a565b92915050565b60006020828403121561585c5761585b613b5a565b5b600061586a84828501615831565b91505092915050565b600061587f8385613c2a565b935061588c838584613eb2565b61589583613c65565b840190509392505050565b600060208201905081810360008301526158bb818486615873565b90509392505050565b60006040820190506158d96000830185613d66565b6158e66020830184613fde565b9392505050565b6000606082019050615902600083018661577c565b61590f6020830185614c7a565b61591c6040830184614bf9565b949350505050565b600061592f82613c1f565b61593981856154d0565b9350615949818560208601613c3b565b80840191505092915050565b60006159618284615924565b915081905092915050565b600061597782613cd1565b915061598283613cd1565b925082820390508181111561599a57615999615625565b5b92915050565b6159a981613cd1565b82525050565b60006159bb83836159a0565b60208301905092915050565b60006159d2826148f4565b6159dc818561537f565b93506159e783614910565b8060005b83811015615a185781516159ff88826159af565b9750615a0a83614938565b9250506001810190506159eb565b5085935050505092915050565b6000606082019050615a3a600083018661577c565b615a476020830185614c7a565b8181036040830152615a5981846159c7565b9050949350505050565b6000604082019050615a78600083018561577c565b615a856020830184614c7a565b9392505050565b6000604082019050615aa1600083018561577c565b615aae6020830184614bf9565b9392505050565b600081519050919050565b600082825260208201905092915050565b6000615adc82615ab5565b615ae68185615ac0565b9350615af6818560208601613c3b565b615aff81613c65565b840191505092915050565b6000608082019050615b1f6000830187613d66565b615b2c6020830186613d66565b615b396040830185613fde565b8181036060830152615b4b8184615ad1565b905095945050505050565b600081519050615b6581613b90565b92915050565b600060208284031215615b8157615b80613b5a565b5b6000615b8f84828501615b56565b91505092915050565b6000606082019050615bad600083018661521b565b615bba6020830185614c7a565b615bc76040830184614bf9565b94935050505056fea26469706673582212200eb08c26c3542c5c9c4560e462876f5bb2f5cbe65e44c3ea9da70e6ba208291964736f6c634300081100330000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000104f534d20537562736372697074696f6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034f534d0000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x60806040526004361061031a5760003560e01c8063937506f8116101ab578063c87b56dd116100f7578063de3efc9111610095578063ea66aeb31161006f578063ea66aeb314610c6d578063f2fde38b14610caa578063f6aacfb114610cd3578063fbd6a8af14610d105761031a565b8063de3efc9114610bc8578063e8a3d48514610c05578063e985e9c514610c305761031a565b8063cde317af116100d1578063cde317af14610b10578063cf41175914610b4d578063d480924d14610b76578063d6cd022e14610b9f5761031a565b8063c87b56dd14610a81578063cc2e3ee114610abe578063ccb4807b14610ae75761031a565b8063a2cd995d11610164578063af6f26cd1161013e578063af6f26cd146109b5578063b88d4fde146109f2578063ba4b62bf14610a1b578063bebd74ad14610a585761031a565b8063a2cd995d1461091f578063a9c133c71461095c578063ae38b5cf146109995761031a565b8063937506f81461080c578063940cd05b1461084957806395d89b4114610872578063a0712d681461089d578063a1a39af2146108b9578063a22cb465146108f65761031a565b806342842e0e1161026a57806370a08231116102235780638293744b116101fd5780638293744b1461075257806389cea3dd1461077b5780638da5cb5b146107b8578063911c9874146107e35761031a565b806370a08231146106c1578063715018a6146106fe57806380b9b855146107155761031a565b806342842e0e146105a357806353ca912a146105cc5780636264cc4e146105f55780636352211e146106325780636500d4111461066f5780636afc1334146106985761031a565b806318160ddd116102d75780632de409f3116102b15780632de409f3146104f857806335ca1c79146105355780633912928a1461055e5780633bbed4a01461057a5761031a565b806318160ddd1461046757806323b872dd146104925780632b603c71146104bb5761031a565b806301ffc9a71461031f57806306fdde031461035c578063081812fc14610387578063095ea7b3146103c4578063150b7a02146103ed57806317c957091461042a575b600080fd5b34801561032b57600080fd5b5061034660048036038101906103419190613bbc565b610d2c565b6040516103539190613c04565b60405180910390f35b34801561036857600080fd5b50610371610e0e565b60405161037e9190613caf565b60405180910390f35b34801561039357600080fd5b506103ae60048036038101906103a99190613d07565b610ea0565b6040516103bb9190613d75565b60405180910390f35b3480156103d057600080fd5b506103eb60048036038101906103e69190613dbc565b610eec565b005b3480156103f957600080fd5b50610414600480360381019061040f9190613f31565b610f03565b6040516104219190613fc3565b60405180910390f35b34801561043657600080fd5b50610451600480360381019061044c9190613d07565b610f22565b60405161045e9190613fed565b60405180910390f35b34801561047357600080fd5b5061047c610fa8565b6040516104899190613fed565b60405180910390f35b34801561049e57600080fd5b506104b960048036038101906104b49190614008565b610fb2565b005b3480156104c757600080fd5b506104e260048036038101906104dd919061405b565b611030565b6040516104ef9190614264565b60405180910390f35b34801561050457600080fd5b5061051f600480360381019061051a91906142e6565b6110bb565b60405161052c9190614432565b60405180910390f35b34801561054157600080fd5b5061055c60048036038101906105579190613d07565b61114f565b005b610578600480360381019061057391906144f5565b6111c6565b005b34801561058657600080fd5b506105a1600480360381019061059c919061405b565b6111e0565b005b3480156105af57600080fd5b506105ca60048036038101906105c59190614008565b61122c565b005b3480156105d857600080fd5b506105f360048036038101906105ee9190614590565b6112ba565b005b34801561060157600080fd5b5061061c60048036038101906106179190614008565b6112df565b6040516106299190613fed565b60405180910390f35b34801561063e57600080fd5b5061065960048036038101906106549190613d07565b61136b565b6040516106669190613d75565b60405180910390f35b34801561067b57600080fd5b50610696600480360381019061069191906145bd565b6113f1565b005b3480156106a457600080fd5b506106bf60048036038101906106ba9190613d07565b611475565b005b3480156106cd57600080fd5b506106e860048036038101906106e3919061405b565b6114fb565b6040516106f59190613fed565b60405180910390f35b34801561070a57600080fd5b50610713611553565b005b34801561072157600080fd5b5061073c6004803603810190610737919061468c565b611567565b6040516107499190613fed565b60405180910390f35b34801561075e57600080fd5b506107796004803603810190610774919061473e565b6115ef565b005b34801561078757600080fd5b506107a2600480360381019061079d919061405b565b611664565b6040516107af9190613fed565b60405180910390f35b3480156107c457600080fd5b506107cd6116ea565b6040516107da9190613d75565b60405180910390f35b3480156107ef57600080fd5b5061080a6004803603810190610805919061479e565b611713565b005b34801561081857600080fd5b50610833600480360381019061082e91906147de565b61178d565b6040516108409190613fed565b60405180910390f35b34801561085557600080fd5b50610870600480360381019061086b9190614590565b611816565b005b34801561087e57600080fd5b5061088761188d565b6040516108949190613caf565b60405180910390f35b6108b760048036038101906108b29190613d07565b61191f565b005b3480156108c557600080fd5b506108e060048036038101906108db9190613d07565b61196b565b6040516108ed9190613fed565b60405180910390f35b34801561090257600080fd5b5061091d6004803603810190610918919061481e565b6119c2565b005b34801561092b57600080fd5b50610946600480360381019061094191906142e6565b6119fc565b60405161095391906148d9565b60405180910390f35b34801561096857600080fd5b50610983600480360381019061097e91906147de565b611ad3565b60405161099091906149a3565b60405180910390f35b6109b360048036038101906109ae91906149c5565b611b61565b005b3480156109c157600080fd5b506109dc60048036038101906109d7919061468c565b611ba5565b6040516109e99190613fed565b60405180910390f35b3480156109fe57600080fd5b50610a196004803603810190610a149190613f31565b611c2e565b005b348015610a2757600080fd5b50610a426004803603810190610a3d9190613d07565b611c53565b604051610a4f9190613fed565b60405180910390f35b348015610a6457600080fd5b50610a7f6004803603810190610a7a9190614a05565b611cd9565b005b348015610a8d57600080fd5b50610aa86004803603810190610aa39190613d07565b611df2565b604051610ab59190613caf565b60405180910390f35b348015610aca57600080fd5b50610ae56004803603810190610ae0919061405b565b611e7d565b005b348015610af357600080fd5b50610b0e6004803603810190610b099190614a8d565b611eec565b005b348015610b1c57600080fd5b50610b376004803603810190610b329190613d07565b611f63565b604051610b449190613c04565b60405180910390f35b348015610b5957600080fd5b50610b746004803603810190610b6f9190613dbc565b611f75565b005b348015610b8257600080fd5b50610b9d6004803603810190610b989190614ad6565b611f93565b005b348015610bab57600080fd5b50610bc66004803603810190610bc191906149c5565b6120f7565b005b348015610bd457600080fd5b50610bef6004803603810190610bea9190613d07565b612171565b604051610bfc9190613d75565b60405180910390f35b348015610c1157600080fd5b50610c1a6121ff565b604051610c279190613caf565b60405180910390f35b348015610c3c57600080fd5b50610c576004803603810190610c5291906147de565b612286565b604051610c649190613c04565b60405180910390f35b348015610c7957600080fd5b50610c946004803603810190610c8f919061405b565b61230f565b604051610ca191906149a3565b60405180910390f35b348015610cb657600080fd5b50610cd16004803603810190610ccc919061405b565b6123e4565b005b348015610cdf57600080fd5b50610cfa6004803603810190610cf59190613d07565b61245e565b604051610d079190613c04565b60405180910390f35b610d2a6004803603810190610d259190614b32565b6124c2565b005b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610df757507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610e075750610e068261266a565b5b9050919050565b606060078054610e1d90614bc1565b80601f0160208091040260200160405190810160405280929190818152602001828054610e4990614bc1565b8015610e965780601f10610e6b57610100808354040283529160200191610e96565b820191906000526020600020905b815481529060010190602001808311610e7957829003601f168201915b5050505050905090565b6000610eab826126d4565b600d600601600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610ef581612721565b610eff8282612764565b5050565b6000610f108433856128b3565b63150b7a0260e01b9050949350505050565b6000601d73a1f273011d271ec06d35b7e731e7f899391cd9b06347f5a81c9091846040518363ffffffff1660e01b8152600401610f60929190614c08565b602060405180830381865af4158015610f7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa19190614c46565b9050919050565b6000601854905090565b610fbd838383612928565b60277317e46924e6e004c5618bca34feb32c14d55fce51636e520c42909185856040518463ffffffff1660e01b8152600401610ffb93929190614c89565b60006040518083038186803b15801561101357600080fd5b505af4158015611027573d6000803e3d6000fd5b50505050505050565b60606019732008152272e4678d4661891125a070e4c3e5edc86308ce42cc9091846040518363ffffffff1660e01b815260040161106e929190614cc7565b600060405180830381865af415801561108b573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906110b49190614f61565b9050919050565b6110c3613a22565b6019732008152272e4678d4661891125a070e4c3e5edc863fd16883c909185856040518463ffffffff1660e01b815260040161110193929190614fe8565b600060405180830381865af415801561111e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611147919061515d565b905092915050565b6015731b7b48434d041eede56b532f2542ac3e1df42dba638fb14e3b90916111768461136b565b6040518363ffffffff1660e01b81526004016111939291906151ad565b60006040518083038186803b1580156111ab57600080fd5b505af41580156111bf573d6000803e3d6000fd5b5050505050565b6111d0828261294b565b6111db838383612b52565b505050565b6111e8612bda565b80602660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61124783838360405180602001604052806000815250611c2e565b60277317e46924e6e004c5618bca34feb32c14d55fce51636e520c42909185856040518463ffffffff1660e01b815260040161128593929190614c89565b60006040518083038186803b15801561129d57600080fd5b505af41580156112b1573d6000803e3d6000fd5b50505050505050565b6112c2612bda565b80601760006101000a81548160ff02191690831515021790555050565b600060277317e46924e6e004c5618bca34feb32c14d55fce51635908f8e590918686866040518563ffffffff1660e01b815260040161132194939291906151d6565b602060405180830381865af415801561133e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113629190614c46565b90509392505050565b6000600973f7efe8f7f017b7eba93daab7c7518e6a4f90bf2e630266c7a39091846040518363ffffffff1660e01b81526004016113a9929190615222565b602060405180830381865af41580156113c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ea919061524b565b9050919050565b6019732008152272e4678d4661891125a070e4c3e5edc8639895d47d90918a8a8a8a8a8a8a8a6040518a63ffffffff1660e01b815260040161143b99989796959493929190615287565b60006040518083038186803b15801561145357600080fd5b505af4158015611467573d6000803e3d6000fd5b505050505050505050505050565b60006114808261136b565b905061148b81612c53565b6015731b7b48434d041eede56b532f2542ac3e1df42dba63b04686629091836040518363ffffffff1660e01b81526004016114c79291906151ad565b60006040518083038186803b1580156114df57600080fd5b505af41580156114f3573d6000803e3d6000fd5b505050505050565b600061150682612ccc565b600960010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b61155b612bda565b6115656000612d35565b565b6000601d73a1f273011d271ec06d35b7e731e7f899391cd9b0629c1dd4909185856040518463ffffffff1660e01b81526004016115a693929190615341565b602060405180830381865af41580156115c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115e79190614c46565b905092915050565b60277317e46924e6e004c5618bca34feb32c14d55fce51634412be0090918585856040518563ffffffff1660e01b815260040161162f94939291906153fa565b60006040518083038186803b15801561164757600080fd5b505af415801561165b573d6000803e3d6000fd5b50505050505050565b60006019732008152272e4678d4661891125a070e4c3e5edc86373632d479091846040518363ffffffff1660e01b81526004016116a2929190614cc7565b602060405180830381865af41580156116bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e39190614c46565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6015731b7b48434d041eede56b532f2542ac3e1df42dba6311841d7090918361173b8661136b565b6040518463ffffffff1660e01b81526004016117599392919061543a565b60006040518083038186803b15801561177157600080fd5b505af4158015611785573d6000803e3d6000fd5b505050505050565b600060277317e46924e6e004c5618bca34feb32c14d55fce5163c412a736909185856040518463ffffffff1660e01b81526004016117cd93929190614c89565b602060405180830381865af41580156117ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180e9190614c46565b905092915050565b61181e612bda565b600173c4a3392eb009a88e9a8b4101587a1a7bcf80432663da1542a69091836040518363ffffffff1660e01b815260040161185a929190615478565b60006040518083038186803b15801561187257600080fd5b505af4158015611886573d6000803e3d6000fd5b5050505050565b60606008805461189c90614bc1565b80601f01602080910402602001604051908101604052809291908181526020018280546118c890614bc1565b80156119155780601f106118ea57610100808354040283529160200191611915565b820191906000526020600020905b8154815290600101906020018083116118f857829003601f168201915b5050505050905090565b61195e816040518060400160405280600181526020017f200000000000000000000000000000000000000000000000000000000000000081525061294b565b6119683382612df9565b50565b60006015600101600061197d8461136b565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101549050919050565b6119ee6119ce3361230f565b6000815181106119e1576119e06154a1565b5b6020026020010151612721565b6119f88282612e3d565b5050565b611a04613a5b565b601d6001018383604051611a19929190615500565b90815260200160405180910390206040518060c0016040529081600082015481526020016001820154815260200160028201548152602001600382015481526020016004820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016004820160149054906101000a900460ff161515151581525050905092915050565b606060277317e46924e6e004c5618bca34feb32c14d55fce5163c680a5c1909185856040518463ffffffff1660e01b8152600401611b1393929190614c89565b600060405180830381865af4158015611b30573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611b5991906155dc565b905092915050565b611ba182826040518060400160405280600181526020017f20000000000000000000000000000000000000000000000000000000000000008152506111c6565b5050565b6000601d73a1f273011d271ec06d35b7e731e7f899391cd9b063967cf8d1909185856040518463ffffffff1660e01b8152600401611be593929190615341565b602060405180830381865af4158015611c02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c269190614c46565b905092915050565b611c383383612f27565b611c4182612721565b611c4d8484848461306e565b50505050565b6000601d73a1f273011d271ec06d35b7e731e7f899391cd9b063db48b3009091846040518363ffffffff1660e01b8152600401611c91929190614c08565b602060405180830381865af4158015611cae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd29190614c46565b9050919050565b611ce1612bda565b6040518060c00160405280848152602001838152602001600081526020016224ea0042611d0e9190615654565b81526020018273ffffffffffffffffffffffffffffffffffffffff16815260200160011515815250601d6001018686604051611d4b929190615500565b90815260200160405180910390206000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160040160146101000a81548160ff0219169083151502179055509050505050505050565b6060600173c4a3392eb009a88e9a8b4101587a1a7bcf80432663d30eae479091846040518363ffffffff1660e01b8152600401611e30929190615688565b600060405180830381865af4158015611e4d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611e7691906156b1565b9050919050565b6019732008152272e4678d4661891125a070e4c3e5edc863b81093009091836040518363ffffffff1660e01b8152600401611eb9929190614cc7565b60006040518083038186803b158015611ed157600080fd5b505af4158015611ee5573d6000803e3d6000fd5b5050505050565b611ef4612bda565b600173c4a3392eb009a88e9a8b4101587a1a7bcf804326632d5459e29091836040518363ffffffff1660e01b8152600401611f309291906156fa565b60006040518083038186803b158015611f4857600080fd5b505af4158015611f5c573d6000803e3d6000fd5b5050505050565b6000611f6e826130c1565b9050919050565b611f7d612bda565b611f8f611f89836130f1565b8261311d565b5050565b6002810361200c57600173c4a3392eb009a88e9a8b4101587a1a7bcf80432663db6a3cab9091846040518363ffffffff1660e01b8152600401611fd79291906156fa565b60006040518083038186803b158015611fef57600080fd5b505af4158015612003573d6000803e3d6000fd5b505050506120f3565b6003810361208557600173c4a3392eb009a88e9a8b4101587a1a7bcf8043266348b5a5a39091846040518363ffffffff1660e01b81526004016120509291906156fa565b60006040518083038186803b15801561206857600080fd5b505af415801561207c573d6000803e3d6000fd5b505050506120f2565b600173c4a3392eb009a88e9a8b4101587a1a7bcf804326638bebb5869091846040518363ffffffff1660e01b81526004016120c19291906156fa565b60006040518083038186803b1580156120d957600080fd5b505af41580156120ed573d6000803e3d6000fd5b505050505b5b5050565b6120ff612bda565b601d73a1f273011d271ec06d35b7e731e7f899391cd9b0637ca5f858909184846040518463ffffffff1660e01b815260040161213d9392919061572a565b60006040518083038186803b15801561215557600080fd5b505af4158015612169573d6000803e3d6000fd5b505050505050565b60006015731b7b48434d041eede56b532f2542ac3e1df42dba63f1650c05909161219a8561136b565b6040518363ffffffff1660e01b81526004016121b79291906151ad565b602060405180830381865af41580156121d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f8919061524b565b9050919050565b6060600173c4a3392eb009a88e9a8b4101587a1a7bcf804326636ae383de90916040518263ffffffff1660e01b815260040161223b9190615761565b600060405180830381865af4158015612258573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061228191906156b1565b905090565b6000600d73d44fc4f2f36e6a75bca189001f2b243dbc7a0d1263e4e0a723909185856040518463ffffffff1660e01b81526004016122c693929190615783565b602060405180830381865af41580156122e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230791906157ba565b905092915050565b6060600973f7efe8f7f017b7eba93daab7c7518e6a4f90bf2e6303c242519091846040518363ffffffff1660e01b815260040161234d9291906157e7565b602060405180830381865af415801561236a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238e9190615846565b8054806020026020016040519081016040528092919081815260200182805480156123d857602002820191906000526020600020905b8154815260200190600101908083116123c4575b50505050509050919050565b6123ec612bda565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612452576040517fc81abf6000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61245b81612d35565b50565b6000601560010160006124708461136b565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b601d60010182826040516124d7929190615500565b908152602001604051809103902060040160149054906101000a900460ff161580612527575042601d6001018383604051612513929190615500565b908152602001604051809103902060030154105b1561256b5781816040517f06dac5070000000000000000000000000000000000000000000000000000000081526004016125629291906158a0565b60405180910390fd5b6125b98383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061294b565b6001601d60010183836040516125d0929190615500565b9081526020016040518091039020600201546125ec9190615654565b601d6001018383604051612601929190615500565b908152602001604051809103902060020181905550612665338484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061318f565b505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6126dd816130c1565b61271e57806040517f3d2f7ef60000000000000000000000000000000000000000000000000000000081526004016127159190613fed565b60405180910390fd5b50565b61272a8161245e565b15612761576040517f35857a7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b3373ffffffffffffffffffffffffffffffffffffffff166127848261136b565b73ffffffffffffffffffffffffffffffffffffffff16146127de5733816040517fa52847350000000000000000000000000000000000000000000000000000000081526004016127d59291906158c4565b60405180910390fd5b600d73d44fc4f2f36e6a75bca189001f2b243dbc7a0d1263735b7846909184846040518463ffffffff1660e01b815260040161281c939291906158ed565b60006040518083038186803b15801561283457600080fd5b505af4158015612848573d6000803e3d6000fd5b50505050808273ffffffffffffffffffffffffffffffffffffffff1661286d8361136b565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60277317e46924e6e004c5618bca34feb32c14d55fce5163284800ce90918585856040518563ffffffff1660e01b81526004016128f394939291906151d6565b60006040518083038186803b15801561290b57600080fd5b505af415801561291f573d6000803e3d6000fd5b50505050505050565b6129323382612f27565b61293b81612721565b6129468383836131a7565b505050565b60006129578383611567565b90506000601d6001018360405161296e9190615955565b908152602001604051809103902060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060006129ae8385611ba5565b90506000811115612a7e578173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156129ff573d6000803e3d6000fd5b507f885e6f6235626292940f78c947a331f4c7c1d7f50a48b38092cf546bc9c7907a601d60010185604051612a349190615955565b908152602001604051809103902060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682604051612a759291906158c4565b60405180910390a15b602660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc8285612ac6919061596c565b9081150290604051600060405180830381858888f19350505050158015612af1573d6000803e3d6000fd5b506001601d60010185604051612b079190615955565b908152602001604051809103902060020154612b239190615654565b601d60010185604051612b369190615955565b9081526020016040518091039020600201819055505050505050565b612b5c3384612f27565b601d73a1f273011d271ec06d35b7e731e7f899391cd9b063befc0ab6909184846040518463ffffffff1660e01b8152600401612b9a93929190615341565b60006040518083038186803b158015612bb257600080fd5b505af4158015612bc6573d6000803e3d6000fd5b50505050612bd5838383613287565b505050565b3373ffffffffffffffffffffffffffffffffffffffff16612bf96116ea565b73ffffffffffffffffffffffffffffffffffffffff1614612c5157336040517fd4ed9a17000000000000000000000000000000000000000000000000000000008152600401612c489190613d75565b60405180910390fd5b565b600d73d44fc4f2f36e6a75bca189001f2b243dbc7a0d12633f4e7cce909183612c7b8561230f565b6040518463ffffffff1660e01b8152600401612c9993929190615a25565b60006040518083038186803b158015612cb157600080fd5b505af4158015612cc5573d6000803e3d6000fd5b5050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612d32576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b612e3982826040518060400160405280600181526020017f200000000000000000000000000000000000000000000000000000000000000081525061318f565b5050565b8015612eb457600d73d44fc4f2f36e6a75bca189001f2b243dbc7a0d1263b2875b199091846040518363ffffffff1660e01b8152600401612e7f929190615a63565b60006040518083038186803b158015612e9757600080fd5b505af4158015612eab573d6000803e3d6000fd5b50505050612f23565b600d73d44fc4f2f36e6a75bca189001f2b243dbc7a0d12630aeeeecb909184336040518463ffffffff1660e01b8152600401612ef293929190615783565b60006040518083038186803b158015612f0a57600080fd5b505af4158015612f1e573d6000803e3d6000fd5b505050505b5050565b6000612f328261136b565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161480612f745750612f738184612286565b5b8061302657508273ffffffffffffffffffffffffffffffffffffffff16600d73d44fc4f2f36e6a75bca189001f2b243dbc7a0d1263dc6cf67e9091856040518363ffffffff1660e01b8152600401612fcd929190615a8c565b602060405180830381865af4158015612fea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061300e919061524b565b73ffffffffffffffffffffffffffffffffffffffff16145b6130695782826040517fa52847350000000000000000000000000000000000000000000000000000000081526004016130609291906158c4565b60405180910390fd5b505050565b61307a84848484613368565b6130b0576040517fe0c7635200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6130bb8484846131a7565b50505050565b6000600d600601600083815260200190815260200160002060000160149054906101000a900460ff169050919050565b60008060016130fe610fa8565b6131089190615654565b905061311483826134df565b80915050919050565b601d73a1f273011d271ec06d35b7e731e7f899391cd9b063a253d058909184846040518463ffffffff1660e01b815260040161315b9392919061572a565b60006040518083038186803b15801561317357600080fd5b505af4158015613187573d6000803e3d6000fd5b505050505050565b6131a261319b846130f1565b8383613287565b505050565b60006131b2836114fb565b11156131fd576131c1826114fb565b6040517f8b03eb030000000000000000000000000000000000000000000000000000000081526004016131f49190613fed565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613263576040517f9b7cfcb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61326c81613615565b613277838383613684565b6132828383836137d3565b505050565b601d73a1f273011d271ec06d35b7e731e7f899391cd9b063befc0ab6909184846040518463ffffffff1660e01b81526004016132c593929190615341565b60006040518083038186803b1580156132dd57600080fd5b505af41580156132f1573d6000803e3d6000fd5b50505050601d73a1f273011d271ec06d35b7e731e7f899391cd9b063a253d058909185856040518463ffffffff1660e01b81526004016133339392919061572a565b60006040518083038186803b15801561334b57600080fd5b505af415801561335f573d6000803e3d6000fd5b50505050505050565b60006133898473ffffffffffffffffffffffffffffffffffffffff1661388b565b156134d2578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02338786866040518563ffffffff1660e01b81526004016133cd9493929190615b0a565b6020604051808303816000875af192505050801561340957506040513d601f19601f820116820180604052508101906134069190615b6b565b60015b613482573d8060008114613439576040519150601f19603f3d011682016040523d82523d6000602084013e61343e565b606091505b50600081510361347a576040517f9b7cfcb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149150506134d7565b600190505b949350505050565b601760009054906101000a900460ff16613525576040517f03eaac9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361359657816040517f17858bbe00000000000000000000000000000000000000000000000000000000815260040161358d9190613d75565b60405180910390fd5b61359f816130c1565b156135e157806040517f8b474e540000000000000000000000000000000000000000000000000000000081526004016135d89190613fed565b60405180910390fd5b6001601860008282546135f49190615654565b9250508190555061360582826138ae565b613611600083836137d3565b5050565b600d73d44fc4f2f36e6a75bca189001f2b243dbc7a0d1263ad8e62069091836040518363ffffffff1660e01b8152600401613651929190615a8c565b60006040518083038186803b15801561366957600080fd5b505af415801561367d573d6000803e3d6000fd5b5050505050565b600973f7efe8f7f017b7eba93daab7c7518e6a4f90bf2e63a0576ba2909185846040518463ffffffff1660e01b81526004016136c293929190615b98565b60006040518083038186803b1580156136da57600080fd5b505af41580156136ee573d6000803e3d6000fd5b50505050600973f7efe8f7f017b7eba93daab7c7518e6a4f90bf2e63a0576ba2909185846040518463ffffffff1660e01b815260040161373093929190615b98565b60006040518083038186803b15801561374857600080fd5b505af415801561375c573d6000803e3d6000fd5b50505050600973f7efe8f7f017b7eba93daab7c7518e6a4f90bf2e63c213e42f909184846040518463ffffffff1660e01b815260040161379e93929190615b98565b60006040518083038186803b1580156137b657600080fd5b505af41580156137ca573d6000803e3d6000fd5b50505050505050565b808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46060613885836040518060c0016040528060001515815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200184815260200160011515815250613920565b50505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600973f7efe8f7f017b7eba93daab7c7518e6a4f90bf2e63c213e42f909184846040518463ffffffff1660e01b81526004016138ec93929190615b98565b60006040518083038186803b15801561390457600080fd5b505af4158015613918573d6000803e3d6000fd5b505050505050565b80601560010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506060820151816003015560808201518160040190805190602001906139fa929190613aa9565b5060a08201518160050160006101000a81548160ff0219169083151502179055509050505050565b604051806060016040528060608152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000151581525090565b6040518060c0016040528060008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000151581525090565b828054828255906000526020600020908101928215613b22579160200282015b82811115613b215782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190613ac9565b5b509050613b2f9190613b33565b5090565b5b80821115613b4c576000816000905550600101613b34565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613b9981613b64565b8114613ba457600080fd5b50565b600081359050613bb681613b90565b92915050565b600060208284031215613bd257613bd1613b5a565b5b6000613be084828501613ba7565b91505092915050565b60008115159050919050565b613bfe81613be9565b82525050565b6000602082019050613c196000830184613bf5565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613c59578082015181840152602081019050613c3e565b60008484015250505050565b6000601f19601f8301169050919050565b6000613c8182613c1f565b613c8b8185613c2a565b9350613c9b818560208601613c3b565b613ca481613c65565b840191505092915050565b60006020820190508181036000830152613cc98184613c76565b905092915050565b6000819050919050565b613ce481613cd1565b8114613cef57600080fd5b50565b600081359050613d0181613cdb565b92915050565b600060208284031215613d1d57613d1c613b5a565b5b6000613d2b84828501613cf2565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613d5f82613d34565b9050919050565b613d6f81613d54565b82525050565b6000602082019050613d8a6000830184613d66565b92915050565b613d9981613d54565b8114613da457600080fd5b50565b600081359050613db681613d90565b92915050565b60008060408385031215613dd357613dd2613b5a565b5b6000613de185828601613da7565b9250506020613df285828601613cf2565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613e3e82613c65565b810181811067ffffffffffffffff82111715613e5d57613e5c613e06565b5b80604052505050565b6000613e70613b50565b9050613e7c8282613e35565b919050565b600067ffffffffffffffff821115613e9c57613e9b613e06565b5b613ea582613c65565b9050602081019050919050565b82818337600083830152505050565b6000613ed4613ecf84613e81565b613e66565b905082815260208101848484011115613ef057613eef613e01565b5b613efb848285613eb2565b509392505050565b600082601f830112613f1857613f17613dfc565b5b8135613f28848260208601613ec1565b91505092915050565b60008060008060808587031215613f4b57613f4a613b5a565b5b6000613f5987828801613da7565b9450506020613f6a87828801613da7565b9350506040613f7b87828801613cf2565b925050606085013567ffffffffffffffff811115613f9c57613f9b613b5f565b5b613fa887828801613f03565b91505092959194509250565b613fbd81613b64565b82525050565b6000602082019050613fd86000830184613fb4565b92915050565b613fe781613cd1565b82525050565b60006020820190506140026000830184613fde565b92915050565b60008060006060848603121561402157614020613b5a565b5b600061402f86828701613da7565b935050602061404086828701613da7565b925050604061405186828701613cf2565b9150509250925092565b60006020828403121561407157614070613b5a565b5b600061407f84828501613da7565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6140bd81613d54565b82525050565b600082825260208201905092915050565b60006140df82613c1f565b6140e981856140c3565b93506140f9818560208601613c3b565b61410281613c65565b840191505092915050565b61411681613cd1565b82525050565b61412581613be9565b82525050565b600060e08301600083015161414360008601826140b4565b506020830151848203602086015261415b82826140d4565b9150506040830151848203604086015261417582826140d4565b915050606083015161418a606086018261410d565b50608083015161419d608086018261411c565b5060a08301516141b060a086018261411c565b5060c08301516141c360c086018261411c565b508091505092915050565b60006141da838361412b565b905092915050565b6000602082019050919050565b60006141fa82614088565b6142048185614093565b935083602082028501614216856140a4565b8060005b85811015614252578484038952815161423385826141ce565b945061423e836141e2565b925060208a0199505060018101905061421a565b50829750879550505050505092915050565b6000602082019050818103600083015261427e81846141ef565b905092915050565b600080fd5b600080fd5b60008083601f8401126142a6576142a5613dfc565b5b8235905067ffffffffffffffff8111156142c3576142c2614286565b5b6020830191508360018202830111156142df576142de61428b565b5b9250929050565b600080602083850312156142fd576142fc613b5a565b5b600083013567ffffffffffffffff81111561431b5761431a613b5f565b5b61432785828601614290565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061436b83836140b4565b60208301905092915050565b6000602082019050919050565b600061438f82614333565b614399818561433e565b93506143a48361434f565b8060005b838110156143d55781516143bc888261435f565b97506143c783614377565b9250506001810190506143a8565b5085935050505092915050565b600060608301600083015184820360008601526143ff8282614384565b915050602083015161441460208601826140b4565b506040830151614427604086018261411c565b508091505092915050565b6000602082019050818103600083015261444c81846143e2565b905092915050565b600067ffffffffffffffff82111561446f5761446e613e06565b5b61447882613c65565b9050602081019050919050565b600061449861449384614454565b613e66565b9050828152602081018484840111156144b4576144b3613e01565b5b6144bf848285613eb2565b509392505050565b600082601f8301126144dc576144db613dfc565b5b81356144ec848260208601614485565b91505092915050565b60008060006060848603121561450e5761450d613b5a565b5b600061451c86828701613cf2565b935050602061452d86828701613cf2565b925050604084013567ffffffffffffffff81111561454e5761454d613b5f565b5b61455a868287016144c7565b9150509250925092565b61456d81613be9565b811461457857600080fd5b50565b60008135905061458a81614564565b92915050565b6000602082840312156145a6576145a5613b5a565b5b60006145b48482850161457b565b91505092915050565b60008060008060008060008060c0898b0312156145dd576145dc613b5a565b5b60006145eb8b828c01613da7565b985050602089013567ffffffffffffffff81111561460c5761460b613b5f565b5b6146188b828c01614290565b9750975050604089013567ffffffffffffffff81111561463b5761463a613b5f565b5b6146478b828c01614290565b9550955050606061465a8b828c01613cf2565b935050608061466b8b828c0161457b565b92505060a061467c8b828c0161457b565b9150509295985092959890939650565b600080604083850312156146a3576146a2613b5a565b5b60006146b185828601613cf2565b925050602083013567ffffffffffffffff8111156146d2576146d1613b5f565b5b6146de858286016144c7565b9150509250929050565b60008083601f8401126146fe576146fd613dfc565b5b8235905067ffffffffffffffff81111561471b5761471a614286565b5b6020830191508360208202830111156147375761473661428b565b5b9250929050565b60008060006040848603121561475757614756613b5a565b5b600061476586828701613da7565b935050602084013567ffffffffffffffff81111561478657614785613b5f565b5b614792868287016146e8565b92509250509250925092565b600080604083850312156147b5576147b4613b5a565b5b60006147c385828601613cf2565b92505060206147d485828601613da7565b9150509250929050565b600080604083850312156147f5576147f4613b5a565b5b600061480385828601613da7565b925050602061481485828601613da7565b9150509250929050565b6000806040838503121561483557614834613b5a565b5b600061484385828601613da7565b92505060206148548582860161457b565b9150509250929050565b60c082016000820151614874600085018261410d565b506020820151614887602085018261410d565b50604082015161489a604085018261410d565b5060608201516148ad606085018261410d565b5060808201516148c060808501826140b4565b5060a08201516148d360a085018261411c565b50505050565b600060c0820190506148ee600083018461485e565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061492c838361410d565b60208301905092915050565b6000602082019050919050565b6000614950826148f4565b61495a81856148ff565b935061496583614910565b8060005b8381101561499657815161497d8882614920565b975061498883614938565b925050600181019050614969565b5085935050505092915050565b600060208201905081810360008301526149bd8184614945565b905092915050565b600080604083850312156149dc576149db613b5a565b5b60006149ea85828601613cf2565b92505060206149fb85828601613cf2565b9150509250929050565b600080600080600060808688031215614a2157614a20613b5a565b5b600086013567ffffffffffffffff811115614a3f57614a3e613b5f565b5b614a4b88828901614290565b95509550506020614a5e88828901613cf2565b9350506040614a6f88828901613cf2565b9250506060614a8088828901613da7565b9150509295509295909350565b600060208284031215614aa357614aa2613b5a565b5b600082013567ffffffffffffffff811115614ac157614ac0613b5f565b5b614acd848285016144c7565b91505092915050565b60008060408385031215614aed57614aec613b5a565b5b600083013567ffffffffffffffff811115614b0b57614b0a613b5f565b5b614b17858286016144c7565b9250506020614b2885828601613cf2565b9150509250929050565b600080600060408486031215614b4b57614b4a613b5a565b5b6000614b5986828701613cf2565b935050602084013567ffffffffffffffff811115614b7a57614b79613b5f565b5b614b8686828701614290565b92509250509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614bd957607f821691505b602082108103614bec57614beb614b92565b5b50919050565b8082525050565b614c0281613cd1565b82525050565b6000604082019050614c1d6000830185614bf2565b614c2a6020830184614bf9565b9392505050565b600081519050614c4081613cdb565b92915050565b600060208284031215614c5c57614c5b613b5a565b5b6000614c6a84828501614c31565b91505092915050565b8082525050565b614c8381613d54565b82525050565b6000606082019050614c9e6000830186614c73565b614cab6020830185614c7a565b614cb86040830184614c7a565b949350505050565b8082525050565b6000604082019050614cdc6000830185614cc0565b614ce96020830184614c7a565b9392505050565b600067ffffffffffffffff821115614d0b57614d0a613e06565b5b602082029050602081019050919050565b600080fd5b600080fd5b600081519050614d3581613d90565b92915050565b6000614d4e614d4984614454565b613e66565b905082815260208101848484011115614d6a57614d69613e01565b5b614d75848285613c3b565b509392505050565b600082601f830112614d9257614d91613dfc565b5b8151614da2848260208601614d3b565b91505092915050565b600081519050614dba81614564565b92915050565b600060e08284031215614dd657614dd5614d1c565b5b614de060e0613e66565b90506000614df084828501614d26565b600083015250602082015167ffffffffffffffff811115614e1457614e13614d21565b5b614e2084828501614d7d565b602083015250604082015167ffffffffffffffff811115614e4457614e43614d21565b5b614e5084828501614d7d565b6040830152506060614e6484828501614c31565b6060830152506080614e7884828501614dab565b60808301525060a0614e8c84828501614dab565b60a08301525060c0614ea084828501614dab565b60c08301525092915050565b6000614ebf614eba84614cf0565b613e66565b90508083825260208201905060208402830185811115614ee257614ee161428b565b5b835b81811015614f2957805167ffffffffffffffff811115614f0757614f06613dfc565b5b808601614f148982614dc0565b85526020850194505050602081019050614ee4565b5050509392505050565b600082601f830112614f4857614f47613dfc565b5b8151614f58848260208601614eac565b91505092915050565b600060208284031215614f7757614f76613b5a565b5b600082015167ffffffffffffffff811115614f9557614f94613b5f565b5b614fa184828501614f33565b91505092915050565b600082825260208201905092915050565b6000614fc78385614faa565b9350614fd4838584613eb2565b614fdd83613c65565b840190509392505050565b6000604082019050614ffd6000830186614cc0565b8181036020830152615010818486614fbb565b9050949350505050565b600067ffffffffffffffff82111561503557615034613e06565b5b602082029050602081019050919050565b60006150596150548461501a565b613e66565b9050808382526020820190506020840283018581111561507c5761507b61428b565b5b835b818110156150a557806150918882614d26565b84526020840193505060208101905061507e565b5050509392505050565b600082601f8301126150c4576150c3613dfc565b5b81516150d4848260208601615046565b91505092915050565b6000606082840312156150f3576150f2614d1c565b5b6150fd6060613e66565b9050600082015167ffffffffffffffff81111561511d5761511c614d21565b5b615129848285016150af565b600083015250602061513d84828501614d26565b602083015250604061515184828501614dab565b60408301525092915050565b60006020828403121561517357615172613b5a565b5b600082015167ffffffffffffffff81111561519157615190613b5f565b5b61519d848285016150dd565b91505092915050565b8082525050565b60006040820190506151c260008301856151a6565b6151cf6020830184614c7a565b9392505050565b60006080820190506151eb6000830187614c73565b6151f86020830186614c7a565b6152056040830185614c7a565b6152126060830184614bf9565b95945050505050565b8082525050565b6000604082019050615237600083018561521b565b6152446020830184614bf9565b9392505050565b60006020828403121561526157615260613b5a565b5b600061526f84828501614d26565b91505092915050565b61528181613be9565b82525050565b600060e08201905061529c600083018c614cc0565b6152a9602083018b614c7a565b81810360408301526152bc81898b614fbb565b905081810360608301526152d1818789614fbb565b90506152e06080830186614bf9565b6152ed60a0830185615278565b6152fa60c0830184615278565b9a9950505050505050505050565b600061531382613c1f565b61531d8185614faa565b935061532d818560208601613c3b565b61533681613c65565b840191505092915050565b60006060820190506153566000830186614bf2565b6153636020830185614bf9565b81810360408301526153758184615308565b9050949350505050565b600082825260208201905092915050565b600080fd5b82818337505050565b60006153aa838561537f565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156153dd576153dc615390565b5b6020830292506153ee838584615395565b82840190509392505050565b600060608201905061540f6000830187614c73565b61541c6020830186614c7a565b818103604083015261542f81848661539e565b905095945050505050565b600060608201905061544f60008301866151a6565b61545c6020830185614c7a565b6154696040830184614c7a565b949350505050565b8082525050565b600060408201905061548d6000830185615471565b61549a6020830184615278565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081905092915050565b60006154e783856154d0565b93506154f4838584613eb2565b82840190509392505050565b600061550d8284866154db565b91508190509392505050565b600067ffffffffffffffff82111561553457615533613e06565b5b602082029050602081019050919050565b600061555861555384615519565b613e66565b9050808382526020820190506020840283018581111561557b5761557a61428b565b5b835b818110156155a457806155908882614c31565b84526020840193505060208101905061557d565b5050509392505050565b600082601f8301126155c3576155c2613dfc565b5b81516155d3848260208601615545565b91505092915050565b6000602082840312156155f2576155f1613b5a565b5b600082015167ffffffffffffffff8111156156105761560f613b5f565b5b61561c848285016155ae565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061565f82613cd1565b915061566a83613cd1565b925082820190508082111561568257615681615625565b5b92915050565b600060408201905061569d6000830185615471565b6156aa6020830184614bf9565b9392505050565b6000602082840312156156c7576156c6613b5a565b5b600082015167ffffffffffffffff8111156156e5576156e4613b5f565b5b6156f184828501614d7d565b91505092915050565b600060408201905061570f6000830185615471565b81810360208301526157218184615308565b90509392505050565b600060608201905061573f6000830186614bf2565b61574c6020830185614bf9565b6157596040830184614bf9565b949350505050565b60006020820190506157766000830184615471565b92915050565b8082525050565b6000606082019050615798600083018661577c565b6157a56020830185614c7a565b6157b26040830184614c7a565b949350505050565b6000602082840312156157d0576157cf613b5a565b5b60006157de84828501614dab565b91505092915050565b60006040820190506157fc600083018561521b565b6158096020830184614c7a565b9392505050565b6000819050919050565b61582381615810565b811461582e57600080fd5b50565b6000815190506158408161581a565b92915050565b60006020828403121561585c5761585b613b5a565b5b600061586a84828501615831565b91505092915050565b600061587f8385613c2a565b935061588c838584613eb2565b61589583613c65565b840190509392505050565b600060208201905081810360008301526158bb818486615873565b90509392505050565b60006040820190506158d96000830185613d66565b6158e66020830184613fde565b9392505050565b6000606082019050615902600083018661577c565b61590f6020830185614c7a565b61591c6040830184614bf9565b949350505050565b600061592f82613c1f565b61593981856154d0565b9350615949818560208601613c3b565b80840191505092915050565b60006159618284615924565b915081905092915050565b600061597782613cd1565b915061598283613cd1565b925082820390508181111561599a57615999615625565b5b92915050565b6159a981613cd1565b82525050565b60006159bb83836159a0565b60208301905092915050565b60006159d2826148f4565b6159dc818561537f565b93506159e783614910565b8060005b83811015615a185781516159ff88826159af565b9750615a0a83614938565b9250506001810190506159eb565b5085935050505092915050565b6000606082019050615a3a600083018661577c565b615a476020830185614c7a565b8181036040830152615a5981846159c7565b9050949350505050565b6000604082019050615a78600083018561577c565b615a856020830184614c7a565b9392505050565b6000604082019050615aa1600083018561577c565b615aae6020830184614bf9565b9392505050565b600081519050919050565b600082825260208201905092915050565b6000615adc82615ab5565b615ae68185615ac0565b9350615af6818560208601613c3b565b615aff81613c65565b840191505092915050565b6000608082019050615b1f6000830187613d66565b615b2c6020830186613d66565b615b396040830185613fde565b8181036060830152615b4b8184615ad1565b905095945050505050565b600081519050615b6581613b90565b92915050565b600060208284031215615b8157615b80613b5a565b5b6000615b8f84828501615b56565b91505092915050565b6000606082019050615bad600083018661521b565b615bba6020830185614c7a565b615bc76040830184614bf9565b94935050505056fea26469706673582212200eb08c26c3542c5c9c4560e462876f5bb2f5cbe65e44c3ea9da70e6ba208291964736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000104f534d20537562736372697074696f6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034f534d0000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : name (string): OSM Subscription
Arg [1] : symbol (string): OSM
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000010
Arg [3] : 4f534d20537562736372697074696f6e00000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [5] : 4f534d0000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.