Overview
Max Total Supply
1,024 CPHR
Holders
469
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
2 CPHRLoading...
Loading
Loading...
Loading
Loading...
Loading
| # | Exchange | Pair | Price | 24H Volume | % Volume |
|---|
Contract Name:
Cypher
Compiler Version
v0.8.6+commit.11564f7e
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2022-11-09
*/
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0 <0.9.0;
// ===============================================
// TERMS AND CONDITIONS
// https://www.anma.io/legal
// ===============================================
/*
HIDEKI TSUKAMOTO | ANOMALOUS MATERIALS | 15.08.2021
______________.___.__________ ___ _______________________
\_ ___ \__ | |\______ \/ | \_ _____|______ \
/ \ \// | | | ___/ ~ \ __)_ | _/
\ \___\____ | | | \ Y / \| | \
\______ / ______| |____| \___|_ /_______ /|____|_ /
\/\/ \/ \/ \/
*/
/*
* @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;
}
}
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_setOwner(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_setOwner(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
/**
* @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);
}
/**
* @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`, 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 be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @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 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);
/**
* @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 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;
}
}
/**
* @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 `IERC721.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
/**
* @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);
}
/**
* @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
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) private pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overriden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
require(operator != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits a {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver(to).onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}
/**
* @dev This implements an optional extension of {ERC721} defined in the EIP that adds
* enumerability of all the token ids in the contract as well as all token ids owned by each
* account.
*/
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
// Mapping from owner to list of owned token IDs
mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
// Mapping from token ID to index of the owner tokens list
mapping(uint256 => uint256) private _ownedTokensIndex;
// Array with all token ids, used for enumeration
uint256[] private _allTokens;
// Mapping from token id to position in the allTokens array
mapping(uint256 => uint256) private _allTokensIndex;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
if (from == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (from != to) {
_removeTokenFromOwnerEnumeration(from, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (to != from) {
_addTokenToOwnerEnumeration(to, tokenId);
}
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = ERC721.balanceOf(to);
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// 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).
uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
}
struct CypherAttributes
{
uint colorset;
int decay;
int chaos;
int utilRand;
int numChannels;
int[8] density;
int[8] intricacy;
}
struct StringBuilder
{
bytes data;
}
library SB
{
function create(uint256 capacity)
internal pure returns(StringBuilder memory)
{
return StringBuilder(new bytes(capacity + 32));
}
function resize(StringBuilder memory sb, uint256 newCapacity)
internal view
{
StringBuilder memory newSb = create(newCapacity);
assembly
{
let data := mload(sb)
let newData := mload(newSb)
let size := mload(add(data, 32)) // get used byte count
let bytesToCopy := add(size, 32) // copy the used bytes, plus the size field in first 32 bytes
pop(staticcall(
gas(),
0x4,
add(data, 32),
bytesToCopy,
add(newData, 32),
bytesToCopy))
}
sb.data = newSb.data;
}
function resizeIfNeeded(StringBuilder memory sb, uint256 spaceNeeded)
internal view
{
uint capacity;
uint size;
assembly
{
let data := mload(sb)
capacity := sub(mload(data), 32)
size := mload(add(data, 32))
}
uint remaining = capacity - size;
if (remaining >= spaceNeeded)
{
return;
}
uint newCapacity = capacity << 1;
uint newRemaining = newCapacity - size;
if (newRemaining >= spaceNeeded)
{
resize(sb, newCapacity);
}
else
{
newCapacity = spaceNeeded + size;
resize(sb, newCapacity);
}
}
function getString(StringBuilder memory sb)
internal pure returns(string memory)
{
string memory ret;
assembly
{
let data := mload(sb)
ret := add(data, 32)
}
return ret;
}
function writeStr(StringBuilder memory sb, string memory str)
internal view
{
resizeIfNeeded(sb, bytes(str).length);
assembly
{
let data := mload(sb)
let size := mload(add(data, 32))
pop(staticcall(gas(), 0x4, add(str, 32), mload(str), add(size, add(data, 64)), mload(str)))
mstore(add(data, 32), add(size, mload(str)))
}
}
function concat(StringBuilder memory dst, StringBuilder memory src)
internal view
{
string memory asString;
assembly
{
let srcData := mload(src)
asString := add(srcData, 32)
}
writeStr(dst, asString);
}
function writeUint(StringBuilder memory sb, uint u)
internal view
{
if (u > 0)
{
uint len;
uint size;
assembly
{
// get length string will be
len := 0
for {let val := u} gt(val, 0) {val := div(val, 10) len := add(len, 1)}
{
}
// get bytes currently used
let data := mload(sb)
size := mload(add(data, 32))
}
// make sure there's room
resizeIfNeeded(sb, len);
assembly
{
let data := mload(sb)
for {let i := 0 let val := u} lt(i, len) {i := add(i, 1) val := div(val, 10)}
{
// sb.data[64 + size + (len - i - 1)] = (val % 10) + 48
mstore8(add(data, add(63, add(size, sub(len, i)))), add(mod(val, 10), 48))
}
size := add(size, len)
mstore(add(data, 32), size)
}
}
else
{
uint size;
assembly
{
let data := mload(sb)
size := mload(add(data, 32))
}
// make sure there's room
resizeIfNeeded(sb, 1);
assembly
{
let data := mload(sb)
mstore(add(data, 32), add(size, 1))
mstore8(add(data, add(64, size)), 48)
}
}
}
function writeInt(StringBuilder memory sb, int i)
internal view
{
if (i < 0)
{
// write the - sign
uint size;
assembly
{
let data := mload(sb)
size := mload(add(data, 32))
}
resizeIfNeeded(sb, 1);
assembly
{
let data := mload(sb)
mstore(add(data, 32), add(size, 1))
mstore8(add(data, add(64, size)), 45)
}
// now the digits can be written as a uint
i *= -1;
}
writeUint(sb, uint(i));
}
function writeRgb(StringBuilder memory sb, uint256 col)
internal view
{
resizeIfNeeded(sb, 6);
string[16] memory nibbles = [
"0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", "a", "b", "c", "d", "e", "f"];
string memory asStr = string(abi.encodePacked(
nibbles[(col >> 20) & 0xf],
nibbles[(col >> 16) & 0xf],
nibbles[(col >> 12) & 0xf],
nibbles[(col >> 8) & 0xf],
nibbles[(col >> 4) & 0xf],
nibbles[col & 0xf]
));
writeStr(sb, asStr);
}
}
struct Rand
{
uint256 value;
}
library Random
{
function create(uint256 srand)
internal pure returns(Rand memory)
{
Rand memory rand = Rand({value: srand});
return rand;
}
function value(Rand memory rand)
internal pure returns(uint256)
{
rand.value = uint256(keccak256(abi.encodePacked(rand.value)));
return rand.value;
}
// (max inclusive)
function range(Rand memory rand, int256 min, int256 max)
internal pure returns(int256)
{
if (min <= max)
{
uint256 span = uint256(max - min);
return int256(value(rand) % (span + 1)) + min;
}
else
{
return range(rand, max, min);
}
}
}
contract CypherDrawing is Ownable
{
int constant FONT_SIZE = 4;
uint8[1024] private curve;
int8[1024] private noiseTable;
uint24[256][5] private gradients;
function setCurve(uint8[1024] memory newCurve)
public onlyOwner
{
curve = newCurve;
}
function setNoiseTable(int8[1024] memory newNoiseTable)
public onlyOwner
{
noiseTable = newNoiseTable;
}
function setGradients(uint24[256][5] memory newGradients)
public onlyOwner
{
gradients = newGradients;
}
function getAttributes(bytes32 hash)
public view returns (CypherAttributes memory)
{
Rand memory rand = Random.create(uint256(hash));
CypherAttributes memory attributes = createAttributes(rand);
return attributes;
}
function generate(bytes32 hash)
public view returns(string memory)
{
StringBuilder memory b = SB.create(128 * 1024);
SB.writeStr(b, "<svg viewBox='0 0 640 640' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>"
"<style>"
"text{"
"font-size:");
SB.writeInt(b, FONT_SIZE);
SB.writeStr(b, "px;"
"font-family: monospace;"
"fill: #cccccc;"
"}"
"</style>"
"<defs>"
"<filter id='glow'>"
"<feGaussianBlur stdDeviation='3.0' result='coloredBlur'/>"
"<feComponentTransfer in='coloredBlur' result='coloredBlur'>"
"<feFuncA type='linear' slope='0.70'/>"
"</feComponentTransfer>"
"<feMerge>"
"<feMergeNode in='coloredBlur'/>"
"<feMergeNode in='SourceGraphic'/>"
"</feMerge>"
"</filter>"
"</defs>"
"<rect width='640' height='640' fill='#090809'/>"
"<g id='cypher' shape-rendering='geometricPrecision' filter='url(#glow)'>");
Rand memory rand = Random.create(uint256(hash));
CypherAttributes memory attributes = createAttributes(rand);
draw(b, attributes, rand);
SB.writeStr(b, "</g>"
"</svg>");
return SB.getString(b);
}
struct Ring
{
uint id;
int arcs;
int span;
int inner;
int outer;
}
struct SegmentData
{
uint ringId;
uint segId;
int inner;
int outer;
int thick;
int start;
int fin;
EdgeType edge;
FillType fill;
SpanType innerSpanType;
PadType padInner;
SpanType outerSpanType;
PadType padOuter;
uint colour;
}
enum SpanType
{
None,
Arc,
Cap,
Ang,
Brk,
Dotted
}
enum Variant
{
None,
Inner,
Outer,
Double,
Max
}
enum EdgeType
{
None,
Simple
}
enum FillType
{
None,
Block,
Hollow,
Text,
Increment,
Comp
}
enum PadType
{
None,
Single
}
function clamp(int num)
private pure returns(int)
{
return clamp(num, 0, 31);
}
function clamp(int num, int min, int max)
private pure returns(int)
{
return num <= min ? min : num >= max ? max : num;
}
function noise(Rand memory rand)
private view returns(int)
{
return noiseTable[uint(Random.range(rand, 0, 1023))];
}
function createAttributes(Rand memory rand)
private view returns(CypherAttributes memory)
{
int weighted = int8(curve[uint(Random.range(rand, 0, 1023))]);
CypherAttributes memory attributes;
attributes.colorset = (uint(weighted < int(8) ? int(8) : weighted) - 8)/6;
attributes.decay = 32 - clamp(weighted + noise(rand));
attributes.chaos = 32 - clamp(weighted + noise(rand));
attributes.utilRand = Random.range(rand, 0, 1023);
attributes.numChannels = 4 + (clamp(weighted + noise(rand), 0, 32) >> 3);
int count = 0;
while(true)
{
uint idx = uint(Random.range(rand, 0, 7));
if(count == attributes.numChannels)
{
break;
}
else if(attributes.density[idx]==1)
{
continue;
}
else
{
attributes.density[idx]=1;
count++;
}
}
for (uint i = 0; i < 8; ++i)
{
attributes.intricacy[i] = clamp(weighted + noise(rand));
}
return attributes;
}
function getSegmentColour(
CypherAttributes memory atr,
Ring memory ring,
Rand memory rand)
private view returns(uint24)
{
int array_offset = atr.utilRand % 256;
int grad_noise = Random.range(rand, 0, 30);
int colour_index = (array_offset + ring.inner + grad_noise) % 256;
return gradients[atr.colorset][uint(colour_index)];
}
function draw(
StringBuilder memory b,
CypherAttributes memory atr,
Rand memory rand)
private view
{
Ring[16] memory rings = createRings(rand);
// frame
for(uint i=0; i<16; ++i)
{
SB.writeStr(b, "<circle cx='320' cy='320' fill='none' stroke-width='0.1' stroke-opacity='15%' stroke='#");
SB.writeRgb(b, gradients[atr.colorset][uint(rings[i].inner)-1]);
SB.writeStr(b, "' r='");
SB.writeInt(b, rings[i].inner);
SB.writeStr(b, "'/>");
}
// defs & ring
// defs added as we go, ring must be deferred
SB.writeStr(b, "<defs>");
StringBuilder memory ringSvg = SB.create(4096);
for(uint i=0; i<16; i++)
{
uint channelIndex = (i >> 1);
if(atr.density[channelIndex] == 0) continue;
int span = rings[i].span;
uint segs = 8 >> uint(Random.range(rand, 1, 2));
int[] memory sections = new int[](segs);
for(uint g=0; g<segs; g++)
{
sections[g] = 1;
}
{
int increments = int(span)-int(segs);
for(int s=0; s<increments; s++)
{
sections[uint(Random.range(rand, 0, int(segs) - 1))]++;
}
}
int progress = int(span);
// template
SB.writeStr(b, "<g id='variant_r");
SB.writeUint(b, rings[i].id);
SB.writeStr(b, "_v0'>");
for(uint t=0; t<segs; t++)
{
progress -= int(sections[t]); // TODO make sure everything with subtractions happens with ints
SegmentData memory segmentData;
segmentData.ringId = i;
segmentData.segId = t;
segmentData.inner = rings[i].inner;
segmentData.outer = rings[i].outer;
segmentData.thick = rings[i].outer - int(rings[i].inner);
segmentData.start = progress * 5;
segmentData.fin = sections[t] * 5;
segmentData.edge = EdgeType(rings[i].inner % 2);
{
int maxIntricacy = atr.intricacy[channelIndex] >> 3;
segmentData.fill = FillType(Random.range(rand, 2, 2+maxIntricacy));
segmentData.innerSpanType = SpanType(Random.range(rand, 2, 2+maxIntricacy));
segmentData.outerSpanType = SpanType(Random.range(rand, 2, 2+maxIntricacy));
}
segmentData.padInner = PadType(rings[i].outer % 2);
segmentData.padOuter = PadType(rings[i].outer % 2);
segmentData.colour = getSegmentColour(atr, rings[i], rand);
if (Random.range(rand, 0, 10) > 7)
{
segmentData.colour = (segmentData.colour & 0xfefefe) >> 1;
}
drawSegment(
b,
segmentData,
rand);
}
SB.writeStr(b, "</g>");
// arc
SB.writeStr(ringSvg, "<g id='r");
SB.writeUint(ringSvg, i);
SB.writeStr(ringSvg, "'>");
for (uint j = 0; j < uint(rings[i].arcs); j++)
{
if (Random.range(rand, 0, 64) < atr.decay)
{
continue; //THIS HAS THE EFFECT I WAS LOOKING FOR.
}
int chaosAddition = Random.range(rand, 0, 720);
int angle = atr.chaos < Random.range(rand, 0, 64) ? rings[i].span : chaosAddition;
int rotation = (angle * int(j)) * 5;
SB.writeStr(ringSvg, "<g id='r");
SB.writeUint(ringSvg, i);
SB.writeStr(ringSvg, "a");
SB.writeUint(ringSvg, j);
SB.writeStr(ringSvg, "' transform='rotate(");
SB.writeInt(ringSvg, rotation);
SB.writeStr(ringSvg, " 320 320)'><use xlink:href='#variant_r");
SB.writeUint(ringSvg, i);
SB.writeStr(ringSvg, "_v0'/> </g>");
}
uint shifted = 8 << uint(Random.range(rand, 0, 4));
SB.writeStr(ringSvg, "<animateTransform attributeName='transform' attributeType='XML' type='rotate' from='0 320 320' to='");
if (Random.range(rand, 0, 10) > 8)
{
SB.writeStr(ringSvg, "-");
}
SB.writeStr(ringSvg, "360 320 320' dur='");
SB.writeUint(ringSvg, shifted);
SB.writeStr(ringSvg, "s' begin='1s' repeatCount='indefinite'/></g>");
}
SB.writeStr(b, "</defs>");
SB.concat(b, ringSvg);
}
function createRings(Rand memory rand)
private pure returns(Ring[16] memory)
{
uint8[8] memory chf = [0, 0, 0, 0, 0, 0, 0, 0];
for(uint i=0; i<24; i++)
{
chf[uint(Random.range(rand, 0, 7))]++;
}
int[16] memory radii = [int(5), 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5];
for(uint j=0; j<chf.length; j++)
{
int total = int8(chf[j]);
for(int i=0; i<total; i++)
{
uint lower = j*2;
uint upper = (j*2)+3;
uint index = uint(Random.range(rand, int(lower), int(upper)));
int adv = Random.range(rand, i, total);
radii[index % 16]+=(adv*5);
total-=adv;
}
}
Ring[16] memory rings;
uint8[5] memory increments = [12, 18, 24, 36, 72];
int progress = 60;
for(uint i=0; i<16; i++)
{
uint idxInc = uint(Random.range(rand, 0, int(increments.length)-1));
int increment = int8(increments[idxInc]);
int pad = 1;
int thisRingThickness = radii[i];
int innerRadius = progress+pad;
int outerRadius = int(innerRadius+thisRingThickness) - int(pad);
progress += thisRingThickness;
int numArcs = 72/increment;
rings[i] = Ring(
{
id : i,
arcs : numArcs,
span : increment,
inner : innerRadius,
outer : outerRadius
});
}
return rings;
}
function drawSpan(
StringBuilder memory b,
SpanType spanType,
int start,
int fin,
int radius,
PadType pad,
Variant variant,
uint col,
Rand memory rand)
private view
{
if (spanType == SpanType.Arc)
{
arc(b, start, fin, radius, pad, col, rand);
}
else if (spanType == SpanType.Dotted)
{
dotted(b, start, fin, radius, pad, col, rand);
}
else if (spanType == SpanType.Cap)
{
cap(b, start, fin, radius, pad, col, rand);
}
else if (spanType == SpanType.Ang)
{
ang(b, start, fin, radius, pad, variant, col, rand);
}
else if (spanType == SpanType.Brk)
{
brk(b, start, fin, radius, pad, variant, col, rand);
}
}
function drawSegment(
StringBuilder memory b,
SegmentData memory segmentData,
Rand memory rand)
private view
{
SB.writeStr(b, "<g id='r");
SB.writeUint(b, segmentData.ringId);
SB.writeStr(b, "v0s");
SB.writeUint(b, segmentData.segId);
SB.writeStr(b, "'>");
//draw the inner span
drawSpan(
b,
segmentData.innerSpanType,
segmentData.start,
segmentData.fin,
segmentData.inner,
segmentData.padInner,
Variant.Inner,
segmentData.colour,
rand);
//draw the outer span
drawSpan(
b,
segmentData.outerSpanType,
segmentData.start,
segmentData.fin,
segmentData.outer,
segmentData.padOuter,
Variant.Outer,
segmentData.colour,
rand);
//draw the edges (matching)
if (segmentData.edge == EdgeType.Simple)
{
simple(
b,
segmentData.start,
segmentData.fin,
segmentData.outer,
segmentData.padOuter,
segmentData.thick,
segmentData.colour,
rand);
}
int radius = segmentData.inner + ((segmentData.outer-segmentData.inner) / 2);
if (segmentData.fill == FillType.Block)
{
blck(
b,
segmentData.start,
segmentData.fin,
radius,
segmentData.padOuter,
segmentData.thick,
segmentData.colour,
rand);
}
else if (segmentData.fill == FillType.Increment)
{
inc(
b,
segmentData.start,
segmentData.fin,
radius,
segmentData.padOuter,
segmentData.thick,
segmentData.colour,
rand);
}
else if (segmentData.fill == FillType.Text)
{
if (!(segmentData.thick < 5 || segmentData.fin < 30))
{
text(
b,
segmentData.start,
segmentData.fin,
segmentData.inner,
segmentData.colour,
rand);
}
}
else if (segmentData.fill == FillType.Hollow)
{
hollow(
b,
segmentData.start,
segmentData.fin,
segmentData.inner,
segmentData.padOuter,
segmentData.thick,
segmentData.colour,
rand);
}
else if (segmentData.fill == FillType.Comp)
{
blck(
b,
segmentData.start,
segmentData.fin,
radius,
segmentData.padOuter,
segmentData.thick,
segmentData.colour,
rand);
inc(
b,
segmentData.start,
segmentData.fin,
radius,
segmentData.padOuter,
segmentData.thick,
segmentData.colour,
rand);
hollow(
b,
segmentData.start,
segmentData.fin,
segmentData.inner,
segmentData.padOuter,
segmentData.thick,
segmentData.colour,
rand);
if (!(segmentData.thick < 5 || segmentData.fin < 30))
{
text(
b,
segmentData.start,
segmentData.fin,
segmentData.inner,
segmentData.colour,
rand);
}
}
SB.writeStr(b, "</g>");
}
/*fill types*/
function hollow(
StringBuilder memory b,
int start,
int fin,
int radius,
PadType pad,
int thickness,
uint col,
Rand memory rand)
view private
{
int padding = pad == PadType.Single ? int(2) : int(0);
int angleStart = start+padding;
int angleEnd = fin-(padding*2);
int innerRad = radius + padding;
int outerRad = radius + (thickness-padding);
int centreRad = 320 + innerRad;
int len = centreRad + thickness - (padding*2);
SB.writeStr(b, "<g transform='rotate(");
SB.writeInt(b, angleStart);
SB.writeStr(b, " 320 320)'><line y1='320' x1='");
SB.writeInt(b, centreRad);
SB.writeStr(b, "' y2='320' x2='");
SB.writeInt(b, len);
SB.writeStr(b, "' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "'/><circle r='");
SB.writeInt(b, innerRad);
SB.writeStr(b, "' cx='320' cy='320' fill='none' pathLength='360' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "' stroke-dasharray='");
SB.writeInt(b, angleEnd);
SB.writeStr(b, " 360'/><circle r='");
SB.writeInt(b, outerRad);
SB.writeStr(b, "' cx='320' cy='320' fill='none' pathLength='360' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "' stroke-dasharray='");
SB.writeInt(b, angleEnd);
SB.writeStr(b, " 360'/><g transform='rotate(");
SB.writeInt(b, angleEnd);
SB.writeStr(b, " 320 320)'><line y1='320' x1='");
SB.writeInt(b, centreRad);
SB.writeStr(b, "' y2='320' x2='");
SB.writeInt(b, len);
SB.writeStr(b, "' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "'/></g></g>");
}
function randomStrokeWidth(Rand memory rand)
private pure returns(string memory)
{
return Random.range(rand, 0, 9) > 6 ? "0.6" : "0.3";
}
function text(
StringBuilder memory b,
int start,
int fin,
int radius,
uint col,
Rand memory rand)
view private
{
int padding = 2;
int angleStart = start - padding;
uint textId = Random.value(rand);
string[12] memory sym = ["0.421", "0.36", "0.73","0.421", "0.36", "0.73","0.421", "0.36", "0.73", "+", "^", "_"];
string memory chars = sym[uint(Random.range(rand, 0, int(sym.length)-1))];
radius += FONT_SIZE + padding;
SB.writeStr(b, "<g transform='rotate(");
SB.writeInt(b, angleStart-180+fin);
SB.writeStr(b, " 320 320)'><path id='text_path_");
SB.writeUint(b, textId);
SB.writeStr(b, "' d='M");
SB.writeInt(b, 320-radius);
SB.writeStr(b, ", 320 a1, 1 0 0, 0 ");
SB.writeInt(b, radius*2);
SB.writeStr(b, ", 0' pathLength='100' fill='none' stroke-width='0' stroke='red'/><text x='0%' style='fill:#");
SB.writeRgb(b, col);
SB.writeStr(b, ";'><textPath href='#text_path_");
SB.writeUint(b, textId);
SB.writeStr(b, "' pointer-events='none'>");
SB.writeStr(b, chars);
SB.writeStr(b, "</textPath></text></g>");
}
function inc(
StringBuilder memory b,
int start,
int fin,
int radius,
PadType pad,
int thickness,
uint col,
Rand memory rand)
view private
{
int padding = (pad == PadType.Single) ? int(4) : int(0);
int angleStart = start + padding / 2;
int angleEnd = fin - (padding);
int stroke = thickness - padding;
uint incId = Random.value(rand);
SB.writeStr(b, "<g transform='rotate(");
SB.writeInt(b, angleStart);
SB.writeStr(b, " 320 320)'><clipPath id='inc_cutter_");
SB.writeUint(b, incId);
SB.writeStr(b, "'><rect x='0' y='0' width='640' height='320' stroke='black' fill='none' transform='rotate(");
SB.writeInt(b, angleEnd);
SB.writeStr(b, ", 320, 320)' /></clipPath><path d='M");
SB.writeInt(b, 320-radius);
SB.writeStr(b, ", 320 a1, 1 0 0, 0 ");
SB.writeInt(b, radius*2);
SB.writeStr(b, ", 0' pathLength='100' fill='none' stroke-width='");
SB.writeInt(b, stroke);
SB.writeStr(b, "' stroke-opacity='0.4' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-dasharray='0.05 1' clip-path='url(#inc_cutter_");
SB.writeUint(b, incId);
SB.writeStr(b, ")'/></g>");
}
function blck(
StringBuilder memory b,
int start,
int /*fin*/,
int radius,
PadType pad,
int thickness,
uint col,
Rand memory rand)
view private
{
int padding = (pad == PadType.Single) ? int(4) : int(0);
int angleStart = start + padding / 2;
int stroke = thickness - padding;
int opac = Random.range(rand, 2, 8);
SB.writeStr(b, "<g transform='rotate(");
SB.writeInt(b, angleStart);
SB.writeStr(b, " 320 320)'><circle r='");
SB.writeInt(b, radius);
SB.writeStr(b, "' cx='320' cy='320' fill='none' pathLength='359' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-opacity='");
SB.writeInt(b, opac);
SB.writeStr(b, "%' stroke-width='");
SB.writeInt(b, stroke);
SB.writeStr(b, "' stroke-dasharray='");
SB.writeInt(b, angleStart);
SB.writeStr(b, " ");
SB.writeInt(b, 360 - angleStart);
SB.writeStr(b, "'/></g>");
}
/*edge types*/
function simple(
StringBuilder memory b,
int start,
int fin,
int radius,
PadType pad,
int len,
uint col,
Rand memory rand)
view private
{
int padding = (pad == PadType.Single) ? int(1) : int(0);
int angleStart = start + padding;
int angleEnd = fin - (padding * 2);
int centreRad = 320 + radius;
int edgeLength = centreRad - len;
SB.writeStr(b, "<g transform='rotate(");
SB.writeInt(b, angleStart);
SB.writeStr(b, " 320 320)'><line y1='320' x1='");
SB.writeInt(b, centreRad);
SB.writeStr(b, "' y2='320' x2='");
SB.writeInt(b, edgeLength);
SB.writeStr(b, "' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "'/><g transform='rotate(");
SB.writeInt(b, angleEnd);
SB.writeStr(b, " 320 320)'><line y1='320' x1='");
SB.writeInt(b, centreRad);
SB.writeStr(b, "' y2='320' x2='");
SB.writeInt(b, edgeLength);
SB.writeStr(b, "' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "'/></g></g>");
}
/*spans*/
function brk(
StringBuilder memory b,
int start,
int fin,
int radius,
PadType pad,
Variant variant,
uint col,
Rand memory rand)
view private
{
int padding = (pad == PadType.Single) ? int(1) : int(0);
int angleStart = start + padding;
int angleEnd = fin - (padding * 2);
int centreRad = 320 + radius;
int brkSize = 2;
int brkOffset = (variant == Variant.Inner) ? centreRad + brkSize : centreRad - brkSize;
//uint brkId = Rand.next(rand);
SB.writeStr(b, "<g><circle r='");
SB.writeInt(b, radius);
SB.writeStr(b, "' cx='320' cy='320' fill='none' pathLength='359' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "' stroke-dasharray='");
SB.writeInt(b, angleStart);
SB.writeStr(b, " ");
SB.writeInt(b, 360 - angleStart);
SB.writeStr(b, "'/><line y1='320' x1='");
SB.writeInt(b, centreRad);
SB.writeStr(b, "' y2='320' x2='");
SB.writeInt(b, brkOffset);
SB.writeStr(b, "' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "'/><g transform='rotate(");
SB.writeInt(b, angleEnd);
SB.writeStr(b, " 320 320)'><line y1='320' x1='");
SB.writeInt(b, centreRad);
SB.writeStr(b, "' y2='320' x2='");
SB.writeInt(b, brkOffset);
SB.writeStr(b, "' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "'/></g></g>");
}
function ang(
StringBuilder memory b,
int start,
int fin,
int radius,
PadType pad,
Variant variant,
uint col,
Rand memory rand)
view private
{
int padding = (pad == PadType.Single) ? int(1) : int(0);
int angleStart = start + padding;
int angleEnd = fin - (padding * 2);
int angsSize = 2;
int centreRad = 320 + radius;
int centreAng = (variant == Variant.Inner) ? centreRad + angsSize : centreRad - angsSize;
int opac = Random.range(rand, 10, 100);
SB.writeStr(b, "<g transform='rotate(");
SB.writeInt(b, angleStart);
SB.writeStr(b, " 320 320)'><circle r='");
SB.writeInt(b, radius);
SB.writeStr(b, "' cx='320' cy='320' fill='none' pathLength='360' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-opacity='");
SB.writeInt(b, opac);
SB.writeStr(b, "%' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "' stroke-dasharray= '");
SB.writeInt(b, angleEnd);
SB.writeStr(b, " 360'/><polyline points='");
SB.writeInt(b, centreAng);
SB.writeStr(b, ", 320 ");
SB.writeInt(b, centreRad);
SB.writeStr(b, ", 320 ");
SB.writeInt(b, centreRad);
SB.writeStr(b, ", ");
SB.writeInt(b, 320+angsSize);
SB.writeStr(b, "' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' fill='none'/><g transform='rotate(");
SB.writeInt(b, angleEnd);
SB.writeStr(b, " 320 320)'><polyline points='");
SB.writeInt(b, centreAng);
SB.writeStr(b, ", 320 ");
SB.writeInt(b, centreRad);
SB.writeStr(b, ", 320 ");
SB.writeInt(b, centreRad);
SB.writeStr(b, ", ");
SB.writeInt(b, 320-angsSize);
SB.writeStr(b, "' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' fill='none'/></g></g>");
}
function cap(
StringBuilder memory b,
int start,
int fin,
int radius,
PadType pad,
uint col,
Rand memory rand)
view private
{
int padding = (pad == PadType.Single) ? int(1) : int(0);
int angleStart = start + padding;
int angleEnd = fin - (padding * 2);
int gap = angleEnd - 2;
SB.writeStr(b, "<g transform='rotate(");
SB.writeInt(b, angleStart);
SB.writeStr(b, " 320 320)'><circle r='");
SB.writeInt(b, radius);
SB.writeStr(b, "' cx='320' cy='320' fill='none' pathLength='360' stroke-opacity='20%' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "' stroke-dasharray='");
SB.writeInt(b, angleEnd);
SB.writeStr(b, " 360'/><circle r='");
SB.writeInt(b, radius);
SB.writeStr(b, "' cx='320' cy='320' fill='none' pathLength='360' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "' stroke-dasharray='1 ");
SB.writeInt(b, gap);
SB.writeStr(b, " 1 360'/></g>");
}
function dotted(
StringBuilder memory b,
int start,
int fin,
int radius,
PadType pad,
uint col,
Rand memory rand)
view private
{
int padding = (pad == PadType.Single) ? int(1) : int(0);
int angleStart = start + padding;
int angleEnd = fin - (padding * 2);
int gap = angleEnd - 2;
int opac = Random.range(rand, 10, 100);
uint dotId = Random.value(rand);
SB.writeStr(b, "<g transform='rotate(");
SB.writeInt(b, angleStart);
SB.writeStr(b, " 320 320)'><clipPath id='dot_cutter_");
SB.writeUint(b, dotId);
SB.writeStr(b, "'><rect x='0' y='0' width='640' height='320' stroke='black' fill='none' transform='rotate(");
SB.writeInt(b, angleEnd);
SB.writeStr(b, ", 320, 320)' /></clipPath><path d='M");
SB.writeInt(b, 320-radius);
SB.writeStr(b, ", 320 a1, 1 0 0, 0 ");
SB.writeInt(b, radius*2);
SB.writeStr(b, ", 0' pathLength='100' fill='none' stroke-opacity='");
SB.writeInt(b, opac);
SB.writeStr(b, "%' stroke-width='0.4' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-dasharray='0.25 0.25' clip-path='url(#dot_cutter_");
SB.writeUint(b, dotId);
SB.writeStr(b, ")'/><circle r='");
SB.writeInt(b, radius);
SB.writeStr(b, "' cx='320' cy='320' fill='none' pathLength='359' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-width='0.4' stroke-dasharray='1 ");
SB.writeInt(b, gap);
SB.writeStr(b, " 1 360'/></g>");
}
function arc(
StringBuilder memory b,
int start,
int /*fin*/,
int radius,
PadType pad,
uint col,
Rand memory rand)
view private
{
int padding = (pad == PadType.Single) ? int(1) : int(0);
int angleStart = start + padding;
SB.writeStr(b, "<g><circle r='");
SB.writeInt(b, radius);
SB.writeStr(b, "' cx='320' cy='320' fill='none' pathLength='359' stroke='#");
SB.writeRgb(b, col);
SB.writeStr(b, "' stroke-width='");
SB.writeStr(b, randomStrokeWidth(rand));
SB.writeStr(b, "' stroke-dasharray='");
SB.writeInt(b, angleStart);
SB.writeStr(b, " ");
SB.writeInt(b, 360 - angleStart);
SB.writeStr(b, "'/></g>");
}
}
contract CypherMetadata is Ownable
{
using Strings for uint256;
CypherDrawing _drawing;
string private _imageBaseUri;
constructor(
CypherDrawing drawing,
string memory imageBaseUri)
{
_drawing = drawing;
_imageBaseUri = imageBaseUri;
}
function tokenURI(
uint256 tokenId,
bytes32 hash,
uint256 generation,
bool isFirstTokenInGeneration)
public view returns(string memory)
{
return string(abi.encodePacked("data:application/json;utf8,{"
"\"image\":\"data:image/svg+xml;utf8,",
_drawing.generate(hash), "\",",
_commonMetadata(tokenId, hash, generation, isFirstTokenInGeneration),
"}"));
}
function metadata(
uint256 tokenId,
bytes32 hash,
uint256 generation,
bool isFirstTokenInGeneration)
public view returns(string memory)
{
string memory imageUri = bytes(_imageBaseUri).length > 0 ? string(abi.encodePacked(_imageBaseUri, tokenId.toString())) : "";
return string(abi.encodePacked("{"
"\"external_url\": \"", imageUri, "\",",
"\"image\": \"", imageUri, "\",",
_commonMetadata(tokenId, hash, generation, isFirstTokenInGeneration),
"}"));
}
function setDrawing(CypherDrawing drawing)
public onlyOwner
{
_drawing = drawing;
}
function setImageBaseUri(string memory imageBaseUri)
public onlyOwner
{
_imageBaseUri = imageBaseUri;
}
function _commonMetadata(
uint256 tokenId,
bytes32 hash,
uint256 generation,
bool isFirstTokenInGeneration)
private view returns(string memory)
{
CypherAttributes memory attributes = _drawing.getAttributes(hash);
int overall = 0;
for (uint i = 0; i < 8; ++i)
{
overall += attributes.density[i] * attributes.intricacy[i];
}
overall >>= 3;
StringBuilder memory b = SB.create(2048);
SB.writeStr(b, "\"description\": \"Cypher is a generative art project by Hideki Tsukamoto comprised of 1024 tokens calculated and drawn via smart-contract, by the Ethereum Virtual Machine. Cypher is part one of the 'Apex' series.\","
"\"name\": \"Cypher #");
SB.writeUint(b, tokenId);
SB.writeStr(b, "\","
"\"background_color\": \"1a181b\","
"\"attributes\": [");
if (tokenId == 0)
{
SB.writeStr(b, "{"
"\"trait_type\": \"Edition\","
"\"value\": \"Genesis\""
"},");
}
else if (tokenId == 1)
{
SB.writeStr(b, "{"
"\"trait_type\": \"Edition\","
"\"value\": \"Primary\""
"},");
}
else if (tokenId == 2)
{
SB.writeStr(b, "{"
"\"trait_type\": \"Edition\","
"\"value\": \"Secondary\""
"},");
}
else if (tokenId == 3)
{
SB.writeStr(b, "{"
"\"trait_type\": \"Edition\","
"\"value\": \"Tertiary\""
"},");
}
if (isFirstTokenInGeneration)
{
SB.writeStr(b, "{"
"\"trait_type\": \"Edition\","
"\"value\": \"Generation Genesis\""
"},");
}
SB.writeStr(b, "{"
"\"trait_type\": \"Generation\","
"\"value\": \"");
SB.writeUint(b, generation);
SB.writeStr(b, "\"},"
"{"
"\"trait_type\": \"Intricacy\","
"\"value\":\"");
SB.writeStr(b, _attributeValueString_0_32(overall));
SB.writeStr(b, "\"},"
"{"
"\"trait_type\": \"Intricacy Value\","
"\"max_value\": 32,"
"\"value\":");
SB.writeInt(b, overall);
SB.writeStr(b, "},"
"{"
"\"trait_type\": \"Chaos\","
"\"value\":\"");
SB.writeStr(b, _attributeValueString_0_32(attributes.chaos));
SB.writeStr(b, "\"},"
"{"
"\"trait_type\": \"Chaos Value\","
"\"max_value\": 32,"
"\"value\":");
SB.writeInt(b, attributes.chaos);
SB.writeStr(b, "},"
"{"
"\"trait_type\": \"Channels\","
"\"value\":\"");
SB.writeStr(b, _attributeValueString_0_8(attributes.numChannels));
SB.writeStr(b, "\"},"
"{"
"\"trait_type\": \"Channels Value\","
"\"max_value\": 8,"
"\"value\":");
SB.writeInt(b, attributes.numChannels);
SB.writeStr(b, "},"
"{"
"\"trait_type\": \"Decay\","
"\"value\":\"");
SB.writeStr(b, _attributeValueString_0_32(attributes.decay));
SB.writeStr(b, "\"},"
"{"
"\"trait_type\": \"Decay Value\","
"\"max_value\": 32,"
"\"value\":");
SB.writeInt(b, attributes.decay);
SB.writeStr(b, "},"
"{"
"\"trait_type\": \"Level\","
"\"value\":\"");
SB.writeUint(b, attributes.colorset + 1);
SB.writeStr(b, "\"},"
"{"
"\"trait_type\": \"Level Value\","
"\"max_value\": 5,"
"\"value\":");
SB.writeUint(b, attributes.colorset + 1);
SB.writeStr(b, "}"
"]");
return SB.getString(b);
}
function _attributeValueString_0_32(int256 value)
private pure returns(string memory)
{
if (value == 0)
{
return "Void";
}
else if (value <= 2)
{
return "Marginal";
}
else if (value <= 8)
{
return "Low";
}
else if (value <= 23)
{
return "Average";
}
else if (value <= 29)
{
return "High";
}
else if (value <= 31)
{
return "Super";
}
else
{
return "Extreme";
}
}
function _attributeValueString_0_8(int256 value)
private pure returns(string memory)
{
if (value == 0)
{
return "Void";
}
else if (value <= 1)
{
return "Marginal";
}
else if (value <= 2)
{
return "Low";
}
else if (value <= 5)
{
return "Average";
}
else if (value <= 6)
{
return "High";
}
else if (value <= 7)
{
return "Super";
}
else
{
return "Extreme";
}
}
}
contract Cypher is ERC721Enumerable, Ownable
{
uint256 private _maxTokenInvocations;
uint256 private _reservedInvocations;
uint256 private _auctionStartBlock;
uint256 private _auctionEndBlock;
uint256 private _initialFee;
uint256 private _initialDuration;
uint256 private _maxHalvings;
address payable private _recipient;
CypherDrawing private _drawing;
CypherMetadata private _metadata;
mapping(uint256 => bytes32) private _hashes;
mapping(uint256 => uint256) private _generation;
bool _isLocked;
struct ConstructorArgs
{
string name;
string symbol;
uint256 maxTokenInvocations;
uint256 reservedInvocations;
uint256 auctionStartBlock;
uint256 initialFee;
uint256 initialDuration;
uint256 maxHalvings;
address payable recipient;
CypherDrawing drawing;
CypherMetadata meta;
}
constructor(
ConstructorArgs memory args)
ERC721(args.name, args.symbol)
{
_maxTokenInvocations = args.maxTokenInvocations;
_reservedInvocations = args.reservedInvocations;
_auctionStartBlock = args.auctionStartBlock;
_initialFee = args.initialFee;
_initialDuration = args.initialDuration;
_maxHalvings = args.maxHalvings;
_recipient = args.recipient;
_drawing = args.drawing;
_metadata = args.meta;
// minting #0
bytes32 hash = keccak256(
abi.encodePacked(uint(0),
blockhash(block.number - 1)));
_hashes[0] = hash;
_generation[0] = 0;
_safeMint(msg.sender, 0);
}
modifier isUnlocked()
{
require(!_isLocked, "Contract is locked");
_;
}
function lock() public onlyOwner
{
_isLocked = true;
}
function setMaxTokenInvocations(uint256 maxTokenInvocations)
public onlyOwner isUnlocked
{
_maxTokenInvocations = maxTokenInvocations;
}
function setReservedInvocations(uint256 reservedInvocations)
public onlyOwner isUnlocked
{
_reservedInvocations = reservedInvocations;
}
function setAuctionStartBlock(uint256 auctionStartBlock)
public onlyOwner isUnlocked
{
_auctionStartBlock = auctionStartBlock;
}
function setInitialFee(uint256 initialFee)
public onlyOwner isUnlocked
{
_initialFee = initialFee;
}
function setInitialDuration(uint256 initialDuration)
public onlyOwner isUnlocked
{
_initialDuration = initialDuration;
}
function setMaxHalvings(uint256 maxHalvings)
public onlyOwner isUnlocked
{
_maxHalvings = maxHalvings;
}
function setRecipient(address payable recipient)
public onlyOwner
{
_recipient = recipient;
}
function setDrawingContract(CypherDrawing drawing)
public onlyOwner isUnlocked
{
_drawing = drawing;
}
function setMetadataContract(CypherMetadata meta)
public onlyOwner
{
_metadata = meta;
}
function getInfo()
public view returns(
bool hasStarted,
bool hasEnded,
uint256 blocksUntilAuctionStart,
uint256 currentGeneration,
uint256 currentFee,
uint256 blocksUntilNextHalving,
uint256 currentInvocationCount,
uint256 maxTokenInvocations)
{
uint256 nextBlock = block.number + 1;
if (nextBlock >= _auctionStartBlock)
{
hasStarted = _auctionStartBlock != 0;
blocksUntilAuctionStart = 0;
}
else
{
hasStarted = false;
blocksUntilAuctionStart = _auctionStartBlock - nextBlock;
}
if (_auctionEndBlock == 0)
{
hasEnded = false;
(currentGeneration,
currentFee,
blocksUntilNextHalving) = _getAuctionState(nextBlock);
}
else
{
hasEnded = true;
(currentGeneration,
currentFee, ) = _getAuctionState(_auctionEndBlock);
blocksUntilNextHalving = 0;
}
currentInvocationCount = totalSupply();
maxTokenInvocations = _maxTokenInvocations;
}
function purchase()
public payable returns (uint256 tokenId)
{
require(_auctionStartBlock > 0 && block.number >= _auctionStartBlock,
"auction hasn't started yet");
uint256 totalInvocations = totalSupply();
uint256 invocationsRemaining = _maxTokenInvocations - totalInvocations;
require(invocationsRemaining > _reservedInvocations ||
(invocationsRemaining > 0 && msg.sender == owner()),
"max token invocations reached");
uint256 blockNumber = block.number;
if (_auctionEndBlock != 0)
{
blockNumber = _auctionEndBlock;
}
else if (invocationsRemaining == (_reservedInvocations + 1))
{
_auctionEndBlock = block.number;
}
uint256 generation;
uint256 fee;
(generation, fee, ) = _getAuctionState(blockNumber);
require(msg.value == fee, "value doesn't equal cost");
(bool success, ) = _recipient.call{value:msg.value}("");
require(success, "Transfer failed.");
tokenId = totalInvocations;
bytes32 hash = keccak256(
abi.encodePacked(tokenId,
blockhash(block.number - 1),
tokenId > 0 ? _hashes[tokenId - 1] : bytes32(0)));
_hashes[tokenId] = hash;
_generation[tokenId] = generation;
_safeMint(msg.sender, tokenId);
return tokenId;
}
function metadata(uint256 tokenId)
public view returns (string memory)
{
require(_exists(tokenId), "token not minted");
return _metadata.metadata(
tokenId,
_hashes[tokenId],
_generation[tokenId],
_isFirstTokenInGeneration(tokenId));
}
function generate(uint256 tokenId)
public view returns (string memory)
{
require(_exists(tokenId), "token not minted");
return _drawing.generate(_hashes[tokenId]);
}
function tokenURI(uint256 tokenId) public view virtual override
returns (string memory)
{
require(_exists(tokenId), "token not minted");
return _metadata.tokenURI(
tokenId,
_hashes[tokenId],
_generation[tokenId],
_isFirstTokenInGeneration(tokenId));
}
function _getAuctionState(uint256 blockNumber) private view returns (
uint256 currentGeneration,
uint256 currentFee,
uint256 blocksUntilNextHalving)
{
if (_auctionStartBlock == 0)
{
return (0, _initialFee, 0);
}
if (blockNumber < _auctionStartBlock)
{
uint256 firstHalving = _auctionStartBlock + _initialDuration;
return (0, _initialFee, firstHalving - blockNumber);
}
uint256 generation = 0;
uint256 fee = _initialFee;
uint256 duration = _initialDuration;
uint256 nextHalving = _auctionStartBlock + duration;
for (uint256 i = 0; i < _maxHalvings; ++i)
{
if (blockNumber < nextHalving)
{
return (generation, fee, nextHalving - blockNumber);
}
++generation;
fee >>= 1;
duration <<= 1;
nextHalving += duration;
}
return (generation, fee, 0);
}
function _isFirstTokenInGeneration(uint256 tokenId)
private view returns(bool)
{
if (tokenId > 0)
{
return _generation[tokenId] != _generation[tokenId - 1];
}
return true;
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"maxTokenInvocations","type":"uint256"},{"internalType":"uint256","name":"reservedInvocations","type":"uint256"},{"internalType":"uint256","name":"auctionStartBlock","type":"uint256"},{"internalType":"uint256","name":"initialFee","type":"uint256"},{"internalType":"uint256","name":"initialDuration","type":"uint256"},{"internalType":"uint256","name":"maxHalvings","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"contract CypherDrawing","name":"drawing","type":"address"},{"internalType":"contract CypherMetadata","name":"meta","type":"address"}],"internalType":"struct Cypher.ConstructorArgs","name":"args","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"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":"uint256","name":"tokenId","type":"uint256"}],"name":"generate","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getInfo","outputs":[{"internalType":"bool","name":"hasStarted","type":"bool"},{"internalType":"bool","name":"hasEnded","type":"bool"},{"internalType":"uint256","name":"blocksUntilAuctionStart","type":"uint256"},{"internalType":"uint256","name":"currentGeneration","type":"uint256"},{"internalType":"uint256","name":"currentFee","type":"uint256"},{"internalType":"uint256","name":"blocksUntilNextHalving","type":"uint256"},{"internalType":"uint256","name":"currentInvocationCount","type":"uint256"},{"internalType":"uint256","name":"maxTokenInvocations","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":[],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"metadata","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"purchase","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionStartBlock","type":"uint256"}],"name":"setAuctionStartBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract CypherDrawing","name":"drawing","type":"address"}],"name":"setDrawingContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"initialDuration","type":"uint256"}],"name":"setInitialDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"initialFee","type":"uint256"}],"name":"setInitialFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxHalvings","type":"uint256"}],"name":"setMaxHalvings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxTokenInvocations","type":"uint256"}],"name":"setMaxTokenInvocations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract CypherMetadata","name":"meta","type":"address"}],"name":"setMetadataContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"recipient","type":"address"}],"name":"setRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"reservedInvocations","type":"uint256"}],"name":"setReservedInvocations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","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"}]Contract Creation Code
60806040523480156200001157600080fd5b5060405162003190380380620031908339810160408190526200003491620009a3565b80516020808301518251909162000051916000918501906200081c565b508051620000679060019060208401906200081c565b505050620000846200007e620001af60201b60201c565b620001b3565b6040810151600b556060810151600c556080810151600d5560a0810151600f5560c081015160105560e0810151601155610100810151601280546001600160a01b039283166001600160a01b03199182161790915561012083015160138054918416918316919091179055610140830151601480549190931691161790556000806200011260014362000bae565b406040516020016200012e929190918252602082015260400190565b60408051601f19818403018152919052805160209182012060008080527fa31547ce6245cdb9ecea19cf8c7eb9f5974025bb4075011409251ae855b30aed82905560169092527f0263c2b778d062355049effc2dece97bc6547ff8a88a3258daa512061c2153dd8290559150620001a790339062000205565b505062000c90565b3390565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b620002278282604051806020016040528060008152506200022b60201b60201c565b5050565b62000237838362000273565b620002466000848484620003c9565b6200026e5760405162461bcd60e51b8152600401620002659062000b15565b60405180910390fd5b505050565b6001600160a01b038216620002cb5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640162000265565b6000818152600260205260409020546001600160a01b031615620003325760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640162000265565b6200034060008383620004f9565b6001600160a01b03821660009081526003602052604081208054600192906200036b90849062000b93565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000620003ea846001600160a01b0316620005d560201b6200151c1760201c565b15620004ed57604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906200042490339089908890889060040162000abf565b602060405180830381600087803b1580156200043f57600080fd5b505af192505050801562000472575060408051601f3d908101601f191682019092526200046f9181019062000970565b60015b620004d2573d808015620004a3576040519150601f19603f3d011682016040523d82523d6000602084013e620004a8565b606091505b508051620004ca5760405162461bcd60e51b8152600401620002659062000b15565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050620004f1565b5060015b949350505050565b620005118383836200026e60201b620008c91760201c565b6001600160a01b0383166200056f576200056981600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b62000595565b816001600160a01b0316836001600160a01b0316146200059557620005958382620005db565b6001600160a01b038216620005af576200026e8162000688565b826001600160a01b0316826001600160a01b0316146200026e576200026e828262000742565b3b151590565b60006001620005f5846200079360201b62000f711760201c565b62000601919062000bae565b60008381526007602052604090205490915080821462000655576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b6008546000906200069c9060019062000bae565b60008381526009602052604081205460088054939450909284908110620006c757620006c762000c64565b906000526020600020015490508060088381548110620006eb57620006eb62000c64565b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548062000726576200072662000c4e565b6001900381819060005260206000200160009055905550505050565b60006200075a836200079360201b62000f711760201c565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b60006001600160a01b038216620008005760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b606482015260840162000265565b506001600160a01b031660009081526003602052604090205490565b8280546200082a9062000bfb565b90600052602060002090601f0160209004810192826200084e576000855562000899565b82601f106200086957805160ff191683800117855562000899565b8280016001018555821562000899579182015b82811115620008995782518255916020019190600101906200087c565b50620008a7929150620008ab565b5090565b5b80821115620008a75760008155600101620008ac565b80516001600160a01b0381168114620008da57600080fd5b919050565b600082601f830112620008f157600080fd5b81516001600160401b03808211156200090e576200090e62000c7a565b604051601f8301601f19908116603f0116810190828211818310171562000939576200093962000c7a565b816040528381528660208588010111156200095357600080fd5b6200096684602083016020890162000bc8565b9695505050505050565b6000602082840312156200098357600080fd5b81516001600160e01b0319811681146200099c57600080fd5b9392505050565b600060208284031215620009b657600080fd5b81516001600160401b0380821115620009ce57600080fd5b908301906101608286031215620009e457600080fd5b620009ee62000b67565b825182811115620009fe57600080fd5b62000a0c87828601620008df565b82525060208301518281111562000a2257600080fd5b62000a3087828601620008df565b60208301525060408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100915062000a84828401620008c2565b82820152610120915062000a9a828401620008c2565b82820152610140915062000ab0828401620008c2565b91810191909152949350505050565b600060018060a01b03808716835280861660208401525083604083015260806060830152825180608084015262000afe8160a085016020870162000bc8565b601f01601f19169190910160a00195945050505050565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60405161016081016001600160401b038111828210171562000b8d5762000b8d62000c7a565b60405290565b6000821982111562000ba95762000ba962000c38565b500190565b60008282101562000bc35762000bc362000c38565b500390565b60005b8381101562000be557818101518382015260200162000bcb565b8381111562000bf5576000848401525b50505050565b600181811c9082168062000c1057607f821691505b6020821081141562000c3257634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6124f08062000ca06000396000f3fe60806040526004361061017e5760003560e01c806301ffc9a714610183578063066208de146101b857806306fdde03146101da578063081812fc146101fc578063092e59c614610234578063095ea7b31461025457806318160ddd1461027457806323b872dd146102935780632464bb5a146102b35780632f745c59146102d35780633bbed4a0146102f357806342842e0e146103135780634a7dd523146103335780634f6ccce7146103535780635a9b0b89146103735780636352211e146103c557806364edfbf0146103e557806370a08231146103ed578063715018a61461040d578063814121a5146104225780638da5cb5b1461044257806395d89b4114610457578063a22cb4651461046c578063b88d4fde1461048c578063bdf1e06d146104ac578063c13fabaf146104cc578063c87b56dd146104ec578063e3684e391461050c578063e5187f431461052c578063e985e9c51461054c578063ec7c64491461056c578063f2fde38b1461058c578063f83d08ba146105ac575b600080fd5b34801561018f57600080fd5b506101a361019e36600461209c565b6105c1565b60405190151581526020015b60405180910390f35b3480156101c457600080fd5b506101d86101d336600461214c565b6105ec565b005b3480156101e657600080fd5b506101ef61064c565b6040516101af91906121ce565b34801561020857600080fd5b5061021c61021736600461214c565b6106de565b6040516001600160a01b0390911681526020016101af565b34801561024057600080fd5b506101d861024f36600461214c565b610766565b34801561026057600080fd5b506101d861026f366004612070565b6107bd565b34801561028057600080fd5b506008545b6040519081526020016101af565b34801561029f57600080fd5b506101d86102ae366004611f4e565b6108ce565b3480156102bf57600080fd5b506101d86102ce36600461214c565b6108ff565b3480156102df57600080fd5b506102856102ee366004612070565b610956565b3480156102ff57600080fd5b506101d861030e366004611ef1565b6109ec565b34801561031f57600080fd5b506101d861032e366004611f4e565b610a3d565b34801561033f57600080fd5b506101ef61034e36600461214c565b610a58565b34801561035f57600080fd5b5061028561036e36600461214c565b610b15565b34801561037f57600080fd5b50610388610ba8565b6040805198151589529615156020890152958701949094526060860192909252608085015260a084015260c083015260e0820152610100016101af565b3480156103d157600080fd5b5061021c6103e036600461214c565b610c3c565b610285610cb3565b3480156103f957600080fd5b50610285610408366004611ef1565b610f71565b34801561041957600080fd5b506101d8610ff8565b34801561042e57600080fd5b506101d861043d36600461214c565b611033565b34801561044e57600080fd5b5061021c61108a565b34801561046357600080fd5b506101ef611099565b34801561047857600080fd5b506101d861048736600461203d565b6110a8565b34801561049857600080fd5b506101d86104a7366004611f8f565b611169565b3480156104b857600080fd5b506101d86104c7366004611ef1565b6111a1565b3480156104d857600080fd5b506101d86104e736600461214c565b611215565b3480156104f857600080fd5b506101ef61050736600461214c565b61126c565b34801561051857600080fd5b506101ef61052736600461214c565b611306565b34801561053857600080fd5b506101d8610547366004611ef1565b611368565b34801561055857600080fd5b506101a3610567366004611f15565b6113b9565b34801561057857600080fd5b506101d861058736600461214c565b6113e7565b34801561059857600080fd5b506101d86105a7366004611ef1565b61143e565b3480156105b857600080fd5b506101d86114de565b60006001600160e01b0319821663780e9d6360e01b14806105e657506105e682611522565b92915050565b336105f561108a565b6001600160a01b0316146106245760405162461bcd60e51b815260040161061b90612233565b60405180910390fd5b60175460ff16156106475760405162461bcd60e51b815260040161061b906122e3565b601055565b60606000805461065b906123c1565b80601f0160208091040260200160405190810160405280929190818152602001828054610687906123c1565b80156106d45780601f106106a9576101008083540402835291602001916106d4565b820191906000526020600020905b8154815290600101906020018083116106b757829003601f168201915b5050505050905090565b60006106e982611572565b61074a5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b606482015260840161061b565b506000908152600460205260409020546001600160a01b031690565b3361076f61108a565b6001600160a01b0316146107955760405162461bcd60e51b815260040161061b90612233565b60175460ff16156107b85760405162461bcd60e51b815260040161061b906122e3565b600f55565b60006107c882610c3c565b9050806001600160a01b0316836001600160a01b031614156108365760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b606482015260840161061b565b336001600160a01b0382161480610852575061085281336113b9565b6108bf5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776044820152771b995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b60421b606482015260840161061b565b6108c9838361158f565b505050565b6108d833826115fd565b6108f45760405162461bcd60e51b815260040161061b90612268565b6108c98383836116c7565b3361090861108a565b6001600160a01b03161461092e5760405162461bcd60e51b815260040161061b90612233565b60175460ff16156109515760405162461bcd60e51b815260040161061b906122e3565b600d55565b600061096183610f71565b82106109c35760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b606482015260840161061b565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b336109f561108a565b6001600160a01b031614610a1b5760405162461bcd60e51b815260040161061b90612233565b601280546001600160a01b0319166001600160a01b0392909216919091179055565b6108c983838360405180602001604052806000815250611169565b6060610a6382611572565b610a7f5760405162461bcd60e51b815260040161061b906122b9565b601354600083815260156020526040908190205490516304a9bd7d60e21b81526001600160a01b03909216916312a6f5f491610ac19160040190815260200190565b60006040518083038186803b158015610ad957600080fd5b505afa158015610aed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105e691908101906120d6565b6000610b2060085490565b8210610b835760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b606482015260840161061b565b60088281548110610b9657610b96612443565b90600052602060002001549050919050565b60008080808080808080610bbd436001612366565b9050600d548110610bd857600d541515985060009650610bed565b6000985080600d54610bea919061237e565b96505b600e54610c0d5760009750610c0181611860565b91975095509350610c27565b60019750610c1c600e54611860565b509096509450600093505b6008549250600b549150509091929394959697565b6000818152600260205260408120546001600160a01b0316806105e65760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b606482015260840161061b565b600080600d54118015610cc85750600d544310155b610d115760405162461bcd60e51b815260206004820152601a602482015279185d58dd1a5bdb881a185cdb89dd081cdd185c9d1959081e595d60321b604482015260640161061b565b6000610d1c60085490565b9050600081600b54610d2e919061237e565b9050600c54811180610d635750600081118015610d635750610d4e61108a565b6001600160a01b0316336001600160a01b0316145b610daf5760405162461bcd60e51b815260206004820152601d60248201527f6d617820746f6b656e20696e766f636174696f6e732072656163686564000000604482015260640161061b565b600e54439015610dc25750600e54610ddc565b600c54610dd0906001612366565b821415610ddc5743600e555b600080610de883611860565b509092509050348114610e385760405162461bcd60e51b81526020600482015260186024820152771d985b1d5948191bd95cdb89dd08195c5d585b0818dbdcdd60421b604482015260640161061b565b6012546040516000916001600160a01b03169034908381818185875af1925050503d8060008114610e85576040519150601f19603f3d011682016040523d82523d6000602084013e610e8a565b606091505b5050905080610ece5760405162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b604482015260640161061b565b859650600087600143610ee1919061237e565b4060008a11610ef1576000610f10565b60156000610f0060018d61237e565b8152602001908152602001600020545b604080516020810194909452830191909152606082015260800160408051601f19818403018152918152815160209283012060008b815260158452828120829055601690935291208590559050610f67338961194f565b5050505050505090565b60006001600160a01b038216610fdc5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b606482015260840161061b565b506001600160a01b031660009081526003602052604090205490565b3361100161108a565b6001600160a01b0316146110275760405162461bcd60e51b815260040161061b90612233565b611031600061196d565b565b3361103c61108a565b6001600160a01b0316146110625760405162461bcd60e51b815260040161061b90612233565b60175460ff16156110855760405162461bcd60e51b815260040161061b906122e3565b600c55565b600a546001600160a01b031690565b60606001805461065b906123c1565b6001600160a01b0382163314156110fd5760405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b604482015260640161061b565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61117333836115fd565b61118f5760405162461bcd60e51b815260040161061b90612268565b61119b848484846119bf565b50505050565b336111aa61108a565b6001600160a01b0316146111d05760405162461bcd60e51b815260040161061b90612233565b60175460ff16156111f35760405162461bcd60e51b815260040161061b906122e3565b601380546001600160a01b0319166001600160a01b0392909216919091179055565b3361121e61108a565b6001600160a01b0316146112445760405162461bcd60e51b815260040161061b90612233565b60175460ff16156112675760405162461bcd60e51b815260040161061b906122e3565b601155565b606061127782611572565b6112935760405162461bcd60e51b815260040161061b906122b9565b6014546000838152601560209081526040808320546016909252909120546001600160a01b0390921691637e99d4f29185916112ce836119f2565b6040516001600160e01b031960e087901b16815260048101949094526024840192909252604483015215156064820152608401610ac1565b606061131182611572565b61132d5760405162461bcd60e51b815260040161061b906122b9565b6014546000838152601560209081526040808320546016909252909120546001600160a01b0390921691633e47894a9185916112ce836119f2565b3361137161108a565b6001600160a01b0316146113975760405162461bcd60e51b815260040161061b90612233565b601480546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b336113f061108a565b6001600160a01b0316146114165760405162461bcd60e51b815260040161061b90612233565b60175460ff16156114395760405162461bcd60e51b815260040161061b906122e3565b600b55565b3361144761108a565b6001600160a01b03161461146d5760405162461bcd60e51b815260040161061b90612233565b6001600160a01b0381166114d25760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161061b565b6114db8161196d565b50565b336114e761108a565b6001600160a01b03161461150d5760405162461bcd60e51b815260040161061b90612233565b6017805460ff19166001179055565b3b151590565b60006001600160e01b031982166380ac58cd60e01b148061155357506001600160e01b03198216635b5e139f60e01b145b806105e657506301ffc9a760e01b6001600160e01b03198316146105e6565b6000908152600260205260409020546001600160a01b0316151590565b600081815260046020526040902080546001600160a01b0319166001600160a01b03841690811790915581906115c482610c3c565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061160882611572565b6116695760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b606482015260840161061b565b600061167483610c3c565b9050806001600160a01b0316846001600160a01b031614806116af5750836001600160a01b03166116a4846106de565b6001600160a01b0316145b806116bf57506116bf81856113b9565b949350505050565b826001600160a01b03166116da82610c3c565b6001600160a01b0316146117425760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b606482015260840161061b565b6001600160a01b0382166117a45760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161061b565b6117af838383611a3d565b6117ba60008261158f565b6001600160a01b03831660009081526003602052604081208054600192906117e390849061237e565b90915550506001600160a01b0382166000908152600360205260408120805460019290611811908490612366565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03868116918217909255915184939187169160008051602061249b83398151915291a4505050565b6000806000600d546000141561187f575050600f546000915081611948565b600d548410156118ba576000601054600d5461189b9190612366565b90506000600f5486836118ae919061237e565b93509350935050611948565b600f54601054600d54600092919083906118d5908390612366565b905060005b60115481101561193a57818910156119085784846118f88b8561237e565b9750975097505050505050611948565b611911856123fc565b9450600193841c939290921b916119288383612366565b9150611933816123fc565b90506118da565b509295509093506000925050505b9193909250565b611969828260405180602001604052806000815250611af5565b5050565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6119ca8484846116c7565b6119d684848484611b28565b61119b5760405162461bcd60e51b815260040161061b906121e1565b60008115611a355760166000611a0960018561237e565b815260200190815260200160002054601660008481526020019081526020016000205414159050919050565b506001919050565b6001600160a01b038316611a9857611a9381600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b611abb565b816001600160a01b0316836001600160a01b031614611abb57611abb8382611c35565b6001600160a01b038216611ad2576108c981611cd2565b826001600160a01b0316826001600160a01b0316146108c9576108c98282611d81565b611aff8383611dc5565b611b0c6000848484611b28565b6108c95760405162461bcd60e51b815260040161061b906121e1565b60006001600160a01b0384163b15611c2a57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290611b6c903390899088908890600401612191565b602060405180830381600087803b158015611b8657600080fd5b505af1925050508015611bb6575060408051601f3d908101601f19168201909252611bb3918101906120b9565b60015b611c10573d808015611be4576040519150601f19603f3d011682016040523d82523d6000602084013e611be9565b606091505b508051611c085760405162461bcd60e51b815260040161061b906121e1565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506116bf565b506001949350505050565b60006001611c4284610f71565b611c4c919061237e565b600083815260076020526040902054909150808214611c9f576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090611ce49060019061237e565b60008381526009602052604081205460088054939450909284908110611d0c57611d0c612443565b906000526020600020015490508060088381548110611d2d57611d2d612443565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480611d6557611d6561242d565b6001900381819060005260206000200160009055905550505050565b6000611d8c83610f71565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160a01b038216611e1b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161061b565b611e2481611572565b15611e705760405162461bcd60e51b815260206004820152601c60248201527b115490cdcc8c4e881d1bdad95b88185b1c9958591e481b5a5b9d195960221b604482015260640161061b565b611e7c60008383611a3d565b6001600160a01b0382166000908152600360205260408120805460019290611ea5908490612366565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b038616908117909155905183929060008051602061249b833981519152908290a45050565b600060208284031215611f0357600080fd5b8135611f0e8161246f565b9392505050565b60008060408385031215611f2857600080fd5b8235611f338161246f565b91506020830135611f438161246f565b809150509250929050565b600080600060608486031215611f6357600080fd5b8335611f6e8161246f565b92506020840135611f7e8161246f565b929592945050506040919091013590565b60008060008060808587031215611fa557600080fd5b8435611fb08161246f565b93506020850135611fc08161246f565b92506040850135915060608501356001600160401b03811115611fe257600080fd5b8501601f81018713611ff357600080fd5b80356120066120018261233f565b61230f565b81815288602083850101111561201b57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b6000806040838503121561205057600080fd5b823561205b8161246f565b915060208301358015158114611f4357600080fd5b6000806040838503121561208357600080fd5b823561208e8161246f565b946020939093013593505050565b6000602082840312156120ae57600080fd5b8135611f0e81612484565b6000602082840312156120cb57600080fd5b8151611f0e81612484565b6000602082840312156120e857600080fd5b81516001600160401b038111156120fe57600080fd5b8201601f8101841361210f57600080fd5b805161211d6120018261233f565b81815285602083850101111561213257600080fd5b612143826020830160208601612395565b95945050505050565b60006020828403121561215e57600080fd5b5035919050565b6000815180845261217d816020860160208601612395565b601f01601f19169290920160200192915050565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906121c490830184612165565b9695505050505050565b602081526000611f0e6020830184612165565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b60208082526010908201526f1d1bdad95b881b9bdd081b5a5b9d195960821b604082015260600190565b60208082526012908201527110dbdb9d1c9858dd081a5cc81b1bd8dad95960721b604082015260600190565b604051601f8201601f191681016001600160401b038111828210171561233757612337612459565b604052919050565b60006001600160401b0382111561235857612358612459565b50601f01601f191660200190565b6000821982111561237957612379612417565b500190565b60008282101561239057612390612417565b500390565b60005b838110156123b0578181015183820152602001612398565b8381111561119b5750506000910152565b600181811c908216806123d557607f821691505b602082108114156123f657634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561241057612410612417565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146114db57600080fd5b6001600160e01b0319811681146114db57600080fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122090b21747925068e2b95a809dfd2235f6a2462418c2d9737be1b7237b1f8bdc7764736f6c634300080600330000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003782dace9d900000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000040519d946311449b33d6b03bb40892faeef12d75000000000000000000000000bd9aa94b28e6362fc610d485ce779ef6baa041aa000000000000000000000000f8ee8798f1fbd48f95ca70d2a68fdda404660b550000000000000000000000000000000000000000000000000000000000000006437970686572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044350485200000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x60806040526004361061017e5760003560e01c806301ffc9a714610183578063066208de146101b857806306fdde03146101da578063081812fc146101fc578063092e59c614610234578063095ea7b31461025457806318160ddd1461027457806323b872dd146102935780632464bb5a146102b35780632f745c59146102d35780633bbed4a0146102f357806342842e0e146103135780634a7dd523146103335780634f6ccce7146103535780635a9b0b89146103735780636352211e146103c557806364edfbf0146103e557806370a08231146103ed578063715018a61461040d578063814121a5146104225780638da5cb5b1461044257806395d89b4114610457578063a22cb4651461046c578063b88d4fde1461048c578063bdf1e06d146104ac578063c13fabaf146104cc578063c87b56dd146104ec578063e3684e391461050c578063e5187f431461052c578063e985e9c51461054c578063ec7c64491461056c578063f2fde38b1461058c578063f83d08ba146105ac575b600080fd5b34801561018f57600080fd5b506101a361019e36600461209c565b6105c1565b60405190151581526020015b60405180910390f35b3480156101c457600080fd5b506101d86101d336600461214c565b6105ec565b005b3480156101e657600080fd5b506101ef61064c565b6040516101af91906121ce565b34801561020857600080fd5b5061021c61021736600461214c565b6106de565b6040516001600160a01b0390911681526020016101af565b34801561024057600080fd5b506101d861024f36600461214c565b610766565b34801561026057600080fd5b506101d861026f366004612070565b6107bd565b34801561028057600080fd5b506008545b6040519081526020016101af565b34801561029f57600080fd5b506101d86102ae366004611f4e565b6108ce565b3480156102bf57600080fd5b506101d86102ce36600461214c565b6108ff565b3480156102df57600080fd5b506102856102ee366004612070565b610956565b3480156102ff57600080fd5b506101d861030e366004611ef1565b6109ec565b34801561031f57600080fd5b506101d861032e366004611f4e565b610a3d565b34801561033f57600080fd5b506101ef61034e36600461214c565b610a58565b34801561035f57600080fd5b5061028561036e36600461214c565b610b15565b34801561037f57600080fd5b50610388610ba8565b6040805198151589529615156020890152958701949094526060860192909252608085015260a084015260c083015260e0820152610100016101af565b3480156103d157600080fd5b5061021c6103e036600461214c565b610c3c565b610285610cb3565b3480156103f957600080fd5b50610285610408366004611ef1565b610f71565b34801561041957600080fd5b506101d8610ff8565b34801561042e57600080fd5b506101d861043d36600461214c565b611033565b34801561044e57600080fd5b5061021c61108a565b34801561046357600080fd5b506101ef611099565b34801561047857600080fd5b506101d861048736600461203d565b6110a8565b34801561049857600080fd5b506101d86104a7366004611f8f565b611169565b3480156104b857600080fd5b506101d86104c7366004611ef1565b6111a1565b3480156104d857600080fd5b506101d86104e736600461214c565b611215565b3480156104f857600080fd5b506101ef61050736600461214c565b61126c565b34801561051857600080fd5b506101ef61052736600461214c565b611306565b34801561053857600080fd5b506101d8610547366004611ef1565b611368565b34801561055857600080fd5b506101a3610567366004611f15565b6113b9565b34801561057857600080fd5b506101d861058736600461214c565b6113e7565b34801561059857600080fd5b506101d86105a7366004611ef1565b61143e565b3480156105b857600080fd5b506101d86114de565b60006001600160e01b0319821663780e9d6360e01b14806105e657506105e682611522565b92915050565b336105f561108a565b6001600160a01b0316146106245760405162461bcd60e51b815260040161061b90612233565b60405180910390fd5b60175460ff16156106475760405162461bcd60e51b815260040161061b906122e3565b601055565b60606000805461065b906123c1565b80601f0160208091040260200160405190810160405280929190818152602001828054610687906123c1565b80156106d45780601f106106a9576101008083540402835291602001916106d4565b820191906000526020600020905b8154815290600101906020018083116106b757829003601f168201915b5050505050905090565b60006106e982611572565b61074a5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b606482015260840161061b565b506000908152600460205260409020546001600160a01b031690565b3361076f61108a565b6001600160a01b0316146107955760405162461bcd60e51b815260040161061b90612233565b60175460ff16156107b85760405162461bcd60e51b815260040161061b906122e3565b600f55565b60006107c882610c3c565b9050806001600160a01b0316836001600160a01b031614156108365760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b606482015260840161061b565b336001600160a01b0382161480610852575061085281336113b9565b6108bf5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776044820152771b995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b60421b606482015260840161061b565b6108c9838361158f565b505050565b6108d833826115fd565b6108f45760405162461bcd60e51b815260040161061b90612268565b6108c98383836116c7565b3361090861108a565b6001600160a01b03161461092e5760405162461bcd60e51b815260040161061b90612233565b60175460ff16156109515760405162461bcd60e51b815260040161061b906122e3565b600d55565b600061096183610f71565b82106109c35760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b606482015260840161061b565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b336109f561108a565b6001600160a01b031614610a1b5760405162461bcd60e51b815260040161061b90612233565b601280546001600160a01b0319166001600160a01b0392909216919091179055565b6108c983838360405180602001604052806000815250611169565b6060610a6382611572565b610a7f5760405162461bcd60e51b815260040161061b906122b9565b601354600083815260156020526040908190205490516304a9bd7d60e21b81526001600160a01b03909216916312a6f5f491610ac19160040190815260200190565b60006040518083038186803b158015610ad957600080fd5b505afa158015610aed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105e691908101906120d6565b6000610b2060085490565b8210610b835760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b606482015260840161061b565b60088281548110610b9657610b96612443565b90600052602060002001549050919050565b60008080808080808080610bbd436001612366565b9050600d548110610bd857600d541515985060009650610bed565b6000985080600d54610bea919061237e565b96505b600e54610c0d5760009750610c0181611860565b91975095509350610c27565b60019750610c1c600e54611860565b509096509450600093505b6008549250600b549150509091929394959697565b6000818152600260205260408120546001600160a01b0316806105e65760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b606482015260840161061b565b600080600d54118015610cc85750600d544310155b610d115760405162461bcd60e51b815260206004820152601a602482015279185d58dd1a5bdb881a185cdb89dd081cdd185c9d1959081e595d60321b604482015260640161061b565b6000610d1c60085490565b9050600081600b54610d2e919061237e565b9050600c54811180610d635750600081118015610d635750610d4e61108a565b6001600160a01b0316336001600160a01b0316145b610daf5760405162461bcd60e51b815260206004820152601d60248201527f6d617820746f6b656e20696e766f636174696f6e732072656163686564000000604482015260640161061b565b600e54439015610dc25750600e54610ddc565b600c54610dd0906001612366565b821415610ddc5743600e555b600080610de883611860565b509092509050348114610e385760405162461bcd60e51b81526020600482015260186024820152771d985b1d5948191bd95cdb89dd08195c5d585b0818dbdcdd60421b604482015260640161061b565b6012546040516000916001600160a01b03169034908381818185875af1925050503d8060008114610e85576040519150601f19603f3d011682016040523d82523d6000602084013e610e8a565b606091505b5050905080610ece5760405162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b604482015260640161061b565b859650600087600143610ee1919061237e565b4060008a11610ef1576000610f10565b60156000610f0060018d61237e565b8152602001908152602001600020545b604080516020810194909452830191909152606082015260800160408051601f19818403018152918152815160209283012060008b815260158452828120829055601690935291208590559050610f67338961194f565b5050505050505090565b60006001600160a01b038216610fdc5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b606482015260840161061b565b506001600160a01b031660009081526003602052604090205490565b3361100161108a565b6001600160a01b0316146110275760405162461bcd60e51b815260040161061b90612233565b611031600061196d565b565b3361103c61108a565b6001600160a01b0316146110625760405162461bcd60e51b815260040161061b90612233565b60175460ff16156110855760405162461bcd60e51b815260040161061b906122e3565b600c55565b600a546001600160a01b031690565b60606001805461065b906123c1565b6001600160a01b0382163314156110fd5760405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b604482015260640161061b565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61117333836115fd565b61118f5760405162461bcd60e51b815260040161061b90612268565b61119b848484846119bf565b50505050565b336111aa61108a565b6001600160a01b0316146111d05760405162461bcd60e51b815260040161061b90612233565b60175460ff16156111f35760405162461bcd60e51b815260040161061b906122e3565b601380546001600160a01b0319166001600160a01b0392909216919091179055565b3361121e61108a565b6001600160a01b0316146112445760405162461bcd60e51b815260040161061b90612233565b60175460ff16156112675760405162461bcd60e51b815260040161061b906122e3565b601155565b606061127782611572565b6112935760405162461bcd60e51b815260040161061b906122b9565b6014546000838152601560209081526040808320546016909252909120546001600160a01b0390921691637e99d4f29185916112ce836119f2565b6040516001600160e01b031960e087901b16815260048101949094526024840192909252604483015215156064820152608401610ac1565b606061131182611572565b61132d5760405162461bcd60e51b815260040161061b906122b9565b6014546000838152601560209081526040808320546016909252909120546001600160a01b0390921691633e47894a9185916112ce836119f2565b3361137161108a565b6001600160a01b0316146113975760405162461bcd60e51b815260040161061b90612233565b601480546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b336113f061108a565b6001600160a01b0316146114165760405162461bcd60e51b815260040161061b90612233565b60175460ff16156114395760405162461bcd60e51b815260040161061b906122e3565b600b55565b3361144761108a565b6001600160a01b03161461146d5760405162461bcd60e51b815260040161061b90612233565b6001600160a01b0381166114d25760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161061b565b6114db8161196d565b50565b336114e761108a565b6001600160a01b03161461150d5760405162461bcd60e51b815260040161061b90612233565b6017805460ff19166001179055565b3b151590565b60006001600160e01b031982166380ac58cd60e01b148061155357506001600160e01b03198216635b5e139f60e01b145b806105e657506301ffc9a760e01b6001600160e01b03198316146105e6565b6000908152600260205260409020546001600160a01b0316151590565b600081815260046020526040902080546001600160a01b0319166001600160a01b03841690811790915581906115c482610c3c565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061160882611572565b6116695760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b606482015260840161061b565b600061167483610c3c565b9050806001600160a01b0316846001600160a01b031614806116af5750836001600160a01b03166116a4846106de565b6001600160a01b0316145b806116bf57506116bf81856113b9565b949350505050565b826001600160a01b03166116da82610c3c565b6001600160a01b0316146117425760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b606482015260840161061b565b6001600160a01b0382166117a45760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161061b565b6117af838383611a3d565b6117ba60008261158f565b6001600160a01b03831660009081526003602052604081208054600192906117e390849061237e565b90915550506001600160a01b0382166000908152600360205260408120805460019290611811908490612366565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03868116918217909255915184939187169160008051602061249b83398151915291a4505050565b6000806000600d546000141561187f575050600f546000915081611948565b600d548410156118ba576000601054600d5461189b9190612366565b90506000600f5486836118ae919061237e565b93509350935050611948565b600f54601054600d54600092919083906118d5908390612366565b905060005b60115481101561193a57818910156119085784846118f88b8561237e565b9750975097505050505050611948565b611911856123fc565b9450600193841c939290921b916119288383612366565b9150611933816123fc565b90506118da565b509295509093506000925050505b9193909250565b611969828260405180602001604052806000815250611af5565b5050565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6119ca8484846116c7565b6119d684848484611b28565b61119b5760405162461bcd60e51b815260040161061b906121e1565b60008115611a355760166000611a0960018561237e565b815260200190815260200160002054601660008481526020019081526020016000205414159050919050565b506001919050565b6001600160a01b038316611a9857611a9381600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b611abb565b816001600160a01b0316836001600160a01b031614611abb57611abb8382611c35565b6001600160a01b038216611ad2576108c981611cd2565b826001600160a01b0316826001600160a01b0316146108c9576108c98282611d81565b611aff8383611dc5565b611b0c6000848484611b28565b6108c95760405162461bcd60e51b815260040161061b906121e1565b60006001600160a01b0384163b15611c2a57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290611b6c903390899088908890600401612191565b602060405180830381600087803b158015611b8657600080fd5b505af1925050508015611bb6575060408051601f3d908101601f19168201909252611bb3918101906120b9565b60015b611c10573d808015611be4576040519150601f19603f3d011682016040523d82523d6000602084013e611be9565b606091505b508051611c085760405162461bcd60e51b815260040161061b906121e1565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506116bf565b506001949350505050565b60006001611c4284610f71565b611c4c919061237e565b600083815260076020526040902054909150808214611c9f576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090611ce49060019061237e565b60008381526009602052604081205460088054939450909284908110611d0c57611d0c612443565b906000526020600020015490508060088381548110611d2d57611d2d612443565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480611d6557611d6561242d565b6001900381819060005260206000200160009055905550505050565b6000611d8c83610f71565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160a01b038216611e1b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161061b565b611e2481611572565b15611e705760405162461bcd60e51b815260206004820152601c60248201527b115490cdcc8c4e881d1bdad95b88185b1c9958591e481b5a5b9d195960221b604482015260640161061b565b611e7c60008383611a3d565b6001600160a01b0382166000908152600360205260408120805460019290611ea5908490612366565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b038616908117909155905183929060008051602061249b833981519152908290a45050565b600060208284031215611f0357600080fd5b8135611f0e8161246f565b9392505050565b60008060408385031215611f2857600080fd5b8235611f338161246f565b91506020830135611f438161246f565b809150509250929050565b600080600060608486031215611f6357600080fd5b8335611f6e8161246f565b92506020840135611f7e8161246f565b929592945050506040919091013590565b60008060008060808587031215611fa557600080fd5b8435611fb08161246f565b93506020850135611fc08161246f565b92506040850135915060608501356001600160401b03811115611fe257600080fd5b8501601f81018713611ff357600080fd5b80356120066120018261233f565b61230f565b81815288602083850101111561201b57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b6000806040838503121561205057600080fd5b823561205b8161246f565b915060208301358015158114611f4357600080fd5b6000806040838503121561208357600080fd5b823561208e8161246f565b946020939093013593505050565b6000602082840312156120ae57600080fd5b8135611f0e81612484565b6000602082840312156120cb57600080fd5b8151611f0e81612484565b6000602082840312156120e857600080fd5b81516001600160401b038111156120fe57600080fd5b8201601f8101841361210f57600080fd5b805161211d6120018261233f565b81815285602083850101111561213257600080fd5b612143826020830160208601612395565b95945050505050565b60006020828403121561215e57600080fd5b5035919050565b6000815180845261217d816020860160208601612395565b601f01601f19169290920160200192915050565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906121c490830184612165565b9695505050505050565b602081526000611f0e6020830184612165565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b60208082526010908201526f1d1bdad95b881b9bdd081b5a5b9d195960821b604082015260600190565b60208082526012908201527110dbdb9d1c9858dd081a5cc81b1bd8dad95960721b604082015260600190565b604051601f8201601f191681016001600160401b038111828210171561233757612337612459565b604052919050565b60006001600160401b0382111561235857612358612459565b50601f01601f191660200190565b6000821982111561237957612379612417565b500190565b60008282101561239057612390612417565b500390565b60005b838110156123b0578181015183820152602001612398565b8381111561119b5750506000910152565b600181811c908216806123d557607f821691505b602082108114156123f657634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561241057612410612417565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146114db57600080fd5b6001600160e01b0319811681146114db57600080fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122090b21747925068e2b95a809dfd2235f6a2462418c2d9737be1b7237b1f8bdc7764736f6c63430008060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003782dace9d900000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000040519d946311449b33d6b03bb40892faeef12d75000000000000000000000000bd9aa94b28e6362fc610d485ce779ef6baa041aa000000000000000000000000f8ee8798f1fbd48f95ca70d2a68fdda404660b550000000000000000000000000000000000000000000000000000000000000006437970686572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044350485200000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : args (tuple):
Arg [1] : name (string): Cypher
Arg [2] : symbol (string): CPHR
Arg [3] : maxTokenInvocations (uint256): 1024
Arg [4] : reservedInvocations (uint256): 32
Arg [5] : auctionStartBlock (uint256): 0
Arg [6] : initialFee (uint256): 1024000000000000000000
Arg [7] : initialDuration (uint256): 1
Arg [8] : maxHalvings (uint256): 14
Arg [9] : recipient (address): 0x40519D946311449b33D6b03BB40892faEEF12D75
Arg [10] : drawing (address): 0xBd9aA94b28E6362FC610d485ce779eF6baA041aa
Arg [11] : meta (address): 0xf8Ee8798f1Fbd48F95ca70d2a68fDDa404660b55
-----Encoded View---------------
16 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [2] : 00000000000000000000000000000000000000000000000000000000000001a0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000400
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [6] : 00000000000000000000000000000000000000000000003782dace9d90000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [8] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [9] : 00000000000000000000000040519d946311449b33d6b03bb40892faeef12d75
Arg [10] : 000000000000000000000000bd9aa94b28e6362fc610d485ce779ef6baa041aa
Arg [11] : 000000000000000000000000f8ee8798f1fbd48f95ca70d2a68fdda404660b55
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [13] : 4379706865720000000000000000000000000000000000000000000000000000
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [15] : 4350485200000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
89593:8303:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36263:224;;;;;;;;;;-1:-1:-1;36263:224:0;;;;;:::i;:::-;;:::i;:::-;;;6675:14:1;;6668:22;6650:41;;6638:2;6623:18;36263:224:0;;;;;;;;92161:148;;;;;;;;;;-1:-1:-1;92161:148:0;;;;;:::i;:::-;;:::i;:::-;;23389:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;24948:221::-;;;;;;;;;;-1:-1:-1;24948:221:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;5973:32:1;;;5955:51;;5943:2;5928:18;24948:221:0;5910:102:1;92025:128:0;;;;;;;;;;-1:-1:-1;92025:128:0;;;;;:::i;:::-;;:::i;24471:411::-;;;;;;;;;;-1:-1:-1;24471:411:0;;;;;:::i;:::-;;:::i;36903:113::-;;;;;;;;;;-1:-1:-1;36991:10:0;:17;36903:113;;;7552:25:1;;;7540:2;7525:18;36903:113:0;7507:76:1;25838:339:0;;;;;;;;;;-1:-1:-1;25838:339:0;;;;;:::i;:::-;;:::i;91861:156::-;;;;;;;;;;-1:-1:-1;91861:156:0;;;;;:::i;:::-;;:::i;36571:256::-;;;;;;;;;;-1:-1:-1;36571:256:0;;;;;:::i;:::-;;:::i;92457:121::-;;;;;;;;;;-1:-1:-1;92457:121:0;;;;;:::i;:::-;;:::i;26248:185::-;;;;;;;;;;-1:-1:-1;26248:185:0;;;;;:::i;:::-;;:::i;96006:204::-;;;;;;;;;;-1:-1:-1;96006:204:0;;;;;:::i;:::-;;:::i;37093:233::-;;;;;;;;;;-1:-1:-1;37093:233:0;;;;;:::i;:::-;;:::i;92848:1256::-;;;;;;;;;;;;;:::i;:::-;;;;7058:14:1;;7051:22;7033:41;;7117:14;;7110:22;7105:2;7090:18;;7083:50;7149:18;;;7142:34;;;;7207:2;7192:18;;7185:34;;;;7250:3;7235:19;;7228:35;7294:3;7279:19;;7272:35;7338:3;7323:19;;7316:35;7382:3;7367:19;;7360:35;7020:3;7005:19;92848:1256:0;6987:414:1;23083:239:0;;;;;;;;;;-1:-1:-1;23083:239:0;;;;;:::i;:::-;;:::i;94112:1550::-;;;:::i;22813:208::-;;;;;;;;;;-1:-1:-1;22813:208:0;;;;;:::i;:::-;;:::i;3001:94::-;;;;;;;;;;;;;:::i;91689:164::-;;;;;;;;;;-1:-1:-1;91689:164:0;;;;;:::i;:::-;;:::i;2350:87::-;;;;;;;;;;;;;:::i;23558:104::-;;;;;;;;;;;;;:::i;25241:295::-;;;;;;;;;;-1:-1:-1;25241:295:0;;;;;:::i;:::-;;:::i;26504:328::-;;;;;;;;;;-1:-1:-1;26504:328:0;;;;;:::i;:::-;;:::i;92586:130::-;;;;;;;;;;-1:-1:-1;92586:130:0;;;;;:::i;:::-;;:::i;92317:132::-;;;;;;;;;;-1:-1:-1;92317:132:0;;;;;:::i;:::-;;:::i;96218:345::-;;;;;;;;;;-1:-1:-1;96218:345:0;;;;;:::i;:::-;;:::i;95671:327::-;;;;;;;;;;-1:-1:-1;95671:327:0;;;;;:::i;:::-;;:::i;92724:116::-;;;;;;;;;;-1:-1:-1;92724:116:0;;;;;:::i;:::-;;:::i;25607:164::-;;;;;;;;;;-1:-1:-1;25607:164:0;;;;;:::i;:::-;;:::i;91517:::-;;;;;;;;;;-1:-1:-1;91517:164:0;;;;;:::i;:::-;;:::i;3250:192::-;;;;;;;;;;-1:-1:-1;3250:192:0;;;;;:::i;:::-;;:::i;91436:73::-;;;;;;;;;;;;;:::i;36263:224::-;36365:4;-1:-1:-1;;;;;;36389:50:0;;-1:-1:-1;;;36389:50:0;;:90;;;36443:36;36467:11;36443:23;:36::i;:::-;36382:97;36263:224;-1:-1:-1;;36263:224:0:o;92161:148::-;1304:10;2570:7;:5;:7::i;:::-;-1:-1:-1;;;;;2570:23:0;;2562:68;;;;-1:-1:-1;;;2562:68:0;;;;;;;:::i;:::-;;;;;;;;;91376:9:::1;::::0;::::1;;91375:10;91367:41;;;;-1:-1:-1::0;;;91367:41:0::1;;;;;;;:::i;:::-;92267:16:::2;:34:::0;92161:148::o;23389:100::-;23443:13;23476:5;23469:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23389:100;:::o;24948:221::-;25024:7;25052:16;25060:7;25052;:16::i;:::-;25044:73;;;;-1:-1:-1;;;25044:73:0;;13099:2:1;25044:73:0;;;13081:21:1;13138:2;13118:18;;;13111:30;13177:34;13157:18;;;13150:62;-1:-1:-1;;;13228:18:1;;;13221:42;13280:19;;25044:73:0;13071:234:1;25044:73:0;-1:-1:-1;25137:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;25137:24:0;;24948:221::o;92025:128::-;1304:10;2570:7;:5;:7::i;:::-;-1:-1:-1;;;;;2570:23:0;;2562:68;;;;-1:-1:-1;;;2562:68:0;;;;;;;:::i;:::-;91376:9:::1;::::0;::::1;;91375:10;91367:41;;;;-1:-1:-1::0;;;91367:41:0::1;;;;;;;:::i;:::-;92121:11:::2;:24:::0;92025:128::o;24471:411::-;24552:13;24568:23;24583:7;24568:14;:23::i;:::-;24552:39;;24616:5;-1:-1:-1;;;;;24610:11:0;:2;-1:-1:-1;;;;;24610:11:0;;;24602:57;;;;-1:-1:-1;;;24602:57:0;;14638:2:1;24602:57:0;;;14620:21:1;14677:2;14657:18;;;14650:30;14716:34;14696:18;;;14689:62;-1:-1:-1;;;14767:18:1;;;14760:31;14808:19;;24602:57:0;14610:223:1;24602:57:0;1304:10;-1:-1:-1;;;;;24694:21:0;;;;:62;;-1:-1:-1;24719:37:0;24736:5;1304:10;25607:164;:::i;24719:37::-;24672:168;;;;-1:-1:-1;;;24672:168:0;;11492:2:1;24672:168:0;;;11474:21:1;11531:2;11511:18;;;11504:30;11570:34;11550:18;;;11543:62;-1:-1:-1;;;11621:18:1;;;11614:54;11685:19;;24672:168:0;11464:246:1;24672:168:0;24853:21;24862:2;24866:7;24853:8;:21::i;:::-;24541:341;24471:411;;:::o;25838:339::-;26033:41;1304:10;26066:7;26033:18;:41::i;:::-;26025:103;;;;-1:-1:-1;;;26025:103:0;;;;;;;:::i;:::-;26141:28;26151:4;26157:2;26161:7;26141:9;:28::i;91861:156::-;1304:10;2570:7;:5;:7::i;:::-;-1:-1:-1;;;;;2570:23:0;;2562:68;;;;-1:-1:-1;;;2562:68:0;;;;;;;:::i;:::-;91376:9:::1;::::0;::::1;;91375:10;91367:41;;;;-1:-1:-1::0;;;91367:41:0::1;;;;;;;:::i;:::-;91971:18:::2;:38:::0;91861:156::o;36571:256::-;36668:7;36704:23;36721:5;36704:16;:23::i;:::-;36696:5;:31;36688:87;;;;-1:-1:-1;;;36688:87:0;;8014:2:1;36688:87:0;;;7996:21:1;8053:2;8033:18;;;8026:30;8092:34;8072:18;;;8065:62;-1:-1:-1;;;8143:18:1;;;8136:41;8194:19;;36688:87:0;7986:233:1;36688:87:0;-1:-1:-1;;;;;;36793:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;36571:256::o;92457:121::-;1304:10;2570:7;:5;:7::i;:::-;-1:-1:-1;;;;;2570:23:0;;2562:68;;;;-1:-1:-1;;;2562:68:0;;;;;;;:::i;:::-;92548:10:::1;:22:::0;;-1:-1:-1;;;;;;92548:22:0::1;-1:-1:-1::0;;;;;92548:22:0;;;::::1;::::0;;;::::1;::::0;;92457:121::o;26248:185::-;26386:39;26403:4;26409:2;26413:7;26386:39;;;;;;;;;;;;:16;:39::i;96006:204::-;96072:13;96112:16;96120:7;96112;:16::i;:::-;96104:45;;;;-1:-1:-1;;;96104:45:0;;;;;;;:::i;:::-;96167:8;;;96185:16;;;:7;:16;;;;;;;;96167:35;;-1:-1:-1;;;96167:35:0;;-1:-1:-1;;;;;96167:8:0;;;;:17;;:35;;;;7552:25:1;;;7540:2;7525:18;;7507:76;96167:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;96167:35:0;;;;;;;;;;;;:::i;37093:233::-;37168:7;37204:30;36991:10;:17;;36903:113;37204:30;37196:5;:38;37188:95;;;;-1:-1:-1;;;37188:95:0;;16148:2:1;37188:95:0;;;16130:21:1;16187:2;16167:18;;;16160:30;16226:34;16206:18;;;16199:62;-1:-1:-1;;;16277:18:1;;;16270:42;16329:19;;37188:95:0;16120:234:1;37188:95:0;37301:10;37312:5;37301:17;;;;;;;;:::i;:::-;;;;;;;;;37294:24;;37093:233;;;:::o;92848:1256::-;92910:15;;;;;;;;;93242:16;:12;93257:1;93242:16;:::i;:::-;93222:36;;93286:18;;93273:9;:31;93269:295;;93343:18;;:23;;;-1:-1:-1;93365:1:0;;-1:-1:-1;93269:295:0;;;93474:5;93461:18;;93543:9;93522:18;;:30;;;;:::i;:::-;93496:56;;93269:295;93580:16;;93576:417;;93638:5;93627:16;;93746:27;93763:9;93746:16;:27::i;:::-;93660:113;;-1:-1:-1;93660:113:0;-1:-1:-1;93660:113:0;-1:-1:-1;93576:417:0;;;93835:4;93824:15;;93906:34;93923:16;;93906;:34::i;:::-;-1:-1:-1;93856:84:0;;-1:-1:-1;93856:84:0;-1:-1:-1;93980:1:0;;-1:-1:-1;93576:417:0;36991:10;:17;94005:38;;94076:20;;94054:42;;93211:893;92848:1256;;;;;;;;:::o;23083:239::-;23155:7;23191:16;;;:7;:16;;;;;;-1:-1:-1;;;;;23191:16:0;23226:19;23218:73;;;;-1:-1:-1;;;23218:73:0;;12328:2:1;23218:73:0;;;12310:21:1;12367:2;12347:18;;;12340:30;12406:34;12386:18;;;12379:62;-1:-1:-1;;;12457:18:1;;;12450:39;12506:19;;23218:73:0;12300:231:1;94112:1550:0;94166:15;94228:1;94207:18;;:22;:60;;;;;94249:18;;94233:12;:34;;94207:60;94199:117;;;;-1:-1:-1;;;94199:117:0;;13873:2:1;94199:117:0;;;13855:21:1;13912:2;13892:18;;;13885:30;-1:-1:-1;;;13931:18:1;;;13924:56;13997:18;;94199:117:0;13845:176:1;94199:117:0;94329:24;94356:13;36991:10;:17;;36903:113;94356:13;94329:40;;94380:28;94434:16;94411:20;;:39;;;;:::i;:::-;94380:70;;94502:20;;94479;:43;:111;;;;94563:1;94540:20;:24;:49;;;;;94582:7;:5;:7::i;:::-;-1:-1:-1;;;;;94568:21:0;:10;-1:-1:-1;;;;;94568:21:0;;94540:49;94471:167;;;;-1:-1:-1;;;94471:167:0;;9609:2:1;94471:167:0;;;9591:21:1;9648:2;9628:18;;;9621:30;9687:31;9667:18;;;9660:59;9736:18;;94471:167:0;9581:179:1;94471:167:0;94700:16;;94673:12;;94700:21;94696:231;;-1:-1:-1;94761:16:0;;94696:231;;;94833:20;;:24;;94856:1;94833:24;:::i;:::-;94808:20;:50;94804:123;;;94903:12;94884:16;:31;94804:123;94939:18;94968:11;95012:29;95029:11;95012:16;:29::i;:::-;-1:-1:-1;94990:51:0;;-1:-1:-1;94990:51:0;-1:-1:-1;95062:9:0;:16;;95054:53;;;;-1:-1:-1;;;95054:53:0;;10726:2:1;95054:53:0;;;10708:21:1;10765:2;10745:18;;;10738:30;-1:-1:-1;;;10784:18:1;;;10777:54;10848:18;;95054:53:0;10698:174:1;95054:53:0;95147:10;;:36;;95129:12;;-1:-1:-1;;;;;95147:10:0;;95169:9;;95129:12;95147:36;95129:12;95147:36;95169:9;95147:10;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95128:55;;;95202:7;95194:36;;;;-1:-1:-1;;;95194:36:0;;15040:2:1;95194:36:0;;;15022:21:1;15079:2;15059:18;;;15052:30;-1:-1:-1;;;15098:18:1;;;15091:46;15154:18;;95194:36:0;15012:166:1;95194:36:0;95261:16;95251:26;;95288:12;95344:7;95408:1;95393:12;:16;;;;:::i;:::-;95383:27;95451:1;95441:7;:11;:47;;95486:1;95441:47;;;95455:7;:20;95463:11;95473:1;95463:7;:11;:::i;:::-;95455:20;;;;;;;;;;;;95441:47;95327:162;;;;;;5677:19:1;;;;5712:12;;5705:28;;;;5749:12;;;5742:28;5786:12;;95327:162:0;;;-1:-1:-1;;95327:162:0;;;;;;;;;95303:187;;95327:162;95303:187;;;;95511:16;;;;:7;:16;;;;;:23;;;95545:11;:20;;;;;:33;;;95303:187;-1:-1:-1;95589:30:0;95599:10;95519:7;95589:9;:30::i;:::-;95640:14;;;;;;;94112:1550;:::o;22813:208::-;22885:7;-1:-1:-1;;;;;22913:19:0;;22905:74;;;;-1:-1:-1;;;22905:74:0;;11917:2:1;22905:74:0;;;11899:21:1;11956:2;11936:18;;;11929:30;11995:34;11975:18;;;11968:62;-1:-1:-1;;;12046:18:1;;;12039:40;12096:19;;22905:74:0;11889:232:1;22905:74:0;-1:-1:-1;;;;;;22997:16:0;;;;;:9;:16;;;;;;;22813:208::o;3001:94::-;1304:10;2570:7;:5;:7::i;:::-;-1:-1:-1;;;;;2570:23:0;;2562:68;;;;-1:-1:-1;;;2562:68:0;;;;;;;:::i;:::-;3066:21:::1;3084:1;3066:9;:21::i;:::-;3001:94::o:0;91689:164::-;1304:10;2570:7;:5;:7::i;:::-;-1:-1:-1;;;;;2570:23:0;;2562:68;;;;-1:-1:-1;;;2562:68:0;;;;;;;:::i;:::-;91376:9:::1;::::0;::::1;;91375:10;91367:41;;;;-1:-1:-1::0;;;91367:41:0::1;;;;;;;:::i;:::-;91803:20:::2;:42:::0;91689:164::o;2350:87::-;2423:6;;-1:-1:-1;;;;;2423:6:0;;2350:87::o;23558:104::-;23614:13;23647:7;23640:14;;;;;:::i;25241:295::-;-1:-1:-1;;;;;25344:24:0;;1304:10;25344:24;;25336:62;;;;-1:-1:-1;;;25336:62:0;;10372:2:1;25336:62:0;;;10354:21:1;10411:2;10391:18;;;10384:30;-1:-1:-1;;;10430:18:1;;;10423:55;10495:18;;25336:62:0;10344:175:1;25336:62:0;1304:10;25411:32;;;;:18;:32;;;;;;;;-1:-1:-1;;;;;25411:42:0;;;;;;;;;;;;:53;;-1:-1:-1;;25411:53:0;;;;;;;;;;25480:48;;6650:41:1;;;25411:42:0;;1304:10;25480:48;;6623:18:1;25480:48:0;;;;;;;25241:295;;:::o;26504:328::-;26679:41;1304:10;26712:7;26679:18;:41::i;:::-;26671:103;;;;-1:-1:-1;;;26671:103:0;;;;;;;:::i;:::-;26785:39;26799:4;26805:2;26809:7;26818:5;26785:13;:39::i;:::-;26504:328;;;;:::o;92586:130::-;1304:10;2570:7;:5;:7::i;:::-;-1:-1:-1;;;;;2570:23:0;;2562:68;;;;-1:-1:-1;;;2562:68:0;;;;;;;:::i;:::-;91376:9:::1;::::0;::::1;;91375:10;91367:41;;;;-1:-1:-1::0;;;91367:41:0::1;;;;;;;:::i;:::-;92690:8:::2;:18:::0;;-1:-1:-1;;;;;;92690:18:0::2;-1:-1:-1::0;;;;;92690:18:0;;;::::2;::::0;;;::::2;::::0;;92586:130::o;92317:132::-;1304:10;2570:7;:5;:7::i;:::-;-1:-1:-1;;;;;2570:23:0;;2562:68;;;;-1:-1:-1;;;2562:68:0;;;;;;;:::i;:::-;91376:9:::1;::::0;::::1;;91375:10;91367:41;;;;-1:-1:-1::0;;;91367:41:0::1;;;;;;;:::i;:::-;92415:12:::2;:26:::0;92317:132::o;96218:345::-;96301:13;96341:16;96349:7;96341;:16::i;:::-;96333:45;;;;-1:-1:-1;;;96333:45:0;;;;;;;:::i;:::-;96398:9;;;96454:16;;;:7;:16;;;;;;;;;96485:11;:20;;;;;;;-1:-1:-1;;;;;96398:9:0;;;;:18;;96431:7;;96520:34;96431:7;96520:25;:34::i;:::-;96398:157;;-1:-1:-1;;;;;;96398:157:0;;;;;;;;;;17113:25:1;;;;17154:18;;;17147:34;;;;17197:18;;;17190:34;17267:14;17260:22;17240:18;;;17233:50;17085:19;;96398:157:0;17067:222:1;95671:327:0;95736:13;95775:16;95783:7;95775;:16::i;:::-;95767:45;;;;-1:-1:-1;;;95767:45:0;;;;;;;:::i;:::-;95832:9;;;95889:16;;;:7;:16;;;;;;;;;95920:11;:20;;;;;;;-1:-1:-1;;;;;95832:9:0;;;;:18;;95866:7;;95955:34;95866:7;95955:25;:34::i;92724:116::-;1304:10;2570:7;:5;:7::i;:::-;-1:-1:-1;;;;;2570:23:0;;2562:68;;;;-1:-1:-1;;;2562:68:0;;;;;;;:::i;:::-;92816:9:::1;:16:::0;;-1:-1:-1;;;;;;92816:16:0::1;-1:-1:-1::0;;;;;92816:16:0;;;::::1;::::0;;;::::1;::::0;;92724:116::o;25607:164::-;-1:-1:-1;;;;;25728:25:0;;;25704:4;25728:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;25607:164::o;91517:::-;1304:10;2570:7;:5;:7::i;:::-;-1:-1:-1;;;;;2570:23:0;;2562:68;;;;-1:-1:-1;;;2562:68:0;;;;;;;:::i;:::-;91376:9:::1;::::0;::::1;;91375:10;91367:41;;;;-1:-1:-1::0;;;91367:41:0::1;;;;;;;:::i;:::-;91631:20:::2;:42:::0;91517:164::o;3250:192::-;1304:10;2570:7;:5;:7::i;:::-;-1:-1:-1;;;;;2570:23:0;;2562:68;;;;-1:-1:-1;;;2562:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;3339:22:0;::::1;3331:73;;;::::0;-1:-1:-1;;;3331:73:0;;8845:2:1;3331:73:0::1;::::0;::::1;8827:21:1::0;8884:2;8864:18;;;8857:30;8923:34;8903:18;;;8896:62;-1:-1:-1;;;8974:18:1;;;8967:36;9020:19;;3331:73:0::1;8817:228:1::0;3331:73:0::1;3415:19;3425:8;3415:9;:19::i;:::-;3250:192:::0;:::o;91436:73::-;1304:10;2570:7;:5;:7::i;:::-;-1:-1:-1;;;;;2570:23:0;;2562:68;;;;-1:-1:-1;;;2562:68:0;;;;;;;:::i;:::-;91485:9:::1;:16:::0;;-1:-1:-1;;91485:16:0::1;91497:4;91485:16;::::0;;91436:73::o;12112:387::-;12435:20;12483:8;;;12112:387::o;22444:305::-;22546:4;-1:-1:-1;;;;;;22583:40:0;;-1:-1:-1;;;22583:40:0;;:105;;-1:-1:-1;;;;;;;22640:48:0;;-1:-1:-1;;;22640:48:0;22583:105;:158;;;-1:-1:-1;;;;;;;;;;9896:40:0;;;22705:36;9787:157;28342:127;28407:4;28431:16;;;:7;:16;;;;;;-1:-1:-1;;;;;28431:16:0;:30;;;28342:127::o;32324:174::-;32399:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;32399:29:0;-1:-1:-1;;;;;32399:29:0;;;;;;;;:24;;32453:23;32399:24;32453:14;:23::i;:::-;-1:-1:-1;;;;;32444:46:0;;;;;;;;;;;32324:174;;:::o;28636:348::-;28729:4;28754:16;28762:7;28754;:16::i;:::-;28746:73;;;;-1:-1:-1;;;28746:73:0;;11079:2:1;28746:73:0;;;11061:21:1;11118:2;11098:18;;;11091:30;11157:34;11137:18;;;11130:62;-1:-1:-1;;;11208:18:1;;;11201:42;11260:19;;28746:73:0;11051:234:1;28746:73:0;28830:13;28846:23;28861:7;28846:14;:23::i;:::-;28830:39;;28899:5;-1:-1:-1;;;;;28888:16:0;:7;-1:-1:-1;;;;;28888:16:0;;:51;;;;28932:7;-1:-1:-1;;;;;28908:31:0;:20;28920:7;28908:11;:20::i;:::-;-1:-1:-1;;;;;28908:31:0;;28888:51;:87;;;;28943:32;28960:5;28967:7;28943:16;:32::i;:::-;28880:96;28636:348;-1:-1:-1;;;;28636:348:0:o;31628:578::-;31787:4;-1:-1:-1;;;;;31760:31:0;:23;31775:7;31760:14;:23::i;:::-;-1:-1:-1;;;;;31760:31:0;;31752:85;;;;-1:-1:-1;;;31752:85:0;;14228:2:1;31752:85:0;;;14210:21:1;14267:2;14247:18;;;14240:30;14306:34;14286:18;;;14279:62;-1:-1:-1;;;14357:18:1;;;14350:39;14406:19;;31752:85:0;14200:231:1;31752:85:0;-1:-1:-1;;;;;31856:16:0;;31848:65;;;;-1:-1:-1;;;31848:65:0;;9967:2:1;31848:65:0;;;9949:21:1;10006:2;9986:18;;;9979:30;10045:34;10025:18;;;10018:62;-1:-1:-1;;;10096:18:1;;;10089:34;10140:19;;31848:65:0;9939:226:1;31848:65:0;31926:39;31947:4;31953:2;31957:7;31926:20;:39::i;:::-;32030:29;32047:1;32051:7;32030:8;:29::i;:::-;-1:-1:-1;;;;;32072:15:0;;;;;;:9;:15;;;;;:20;;32091:1;;32072:15;:20;;32091:1;;32072:20;:::i;:::-;;;;-1:-1:-1;;;;;;;32103:13:0;;;;;;:9;:13;;;;;:18;;32120:1;;32103:13;:18;;32120:1;;32103:18;:::i;:::-;;;;-1:-1:-1;;32132:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;32132:21:0;-1:-1:-1;;;;;32132:21:0;;;;;;;;;32171:27;;32132:16;;32171:27;;;;-1:-1:-1;;;;;;;;;;;32171:27:0;;31628:578;;;:::o;96571:1071::-;96650:25;96687:18;96717:30;96769:18;;96791:1;96769:23;96765:91;;;-1:-1:-1;;96829:11:0;;96826:1;;-1:-1:-1;96826:1:0;96818:26;;96765:91;96894:18;;96880:11;:32;96876:200;;;96938:20;96982:16;;96961:18;;:37;;;;:::i;:::-;96938:60;;97021:1;97024:11;;97052;97037:12;:26;;;;:::i;:::-;97013:51;;;;;;;;;96876:200;97135:11;;97176:16;;97225:18;;97088;;97135:11;97176:16;97088:18;;97225:29;;97176:16;;97225:29;:::i;:::-;97203:51;;97272:9;97267:328;97291:12;;97287:1;:16;97267:328;;;97352:11;97338;:25;97334:130;;;97405:10;97417:3;97422:25;97436:11;97422;:25;:::i;:::-;97397:51;;;;;;;;;;;;;97334:130;97480:12;;;:::i;:::-;;-1:-1:-1;97515:1:0;97507:9;;;;97531:14;;;;;97560:23;97531:14;97560:23;;:::i;:::-;;-1:-1:-1;97305:3:0;;;:::i;:::-;;;97267:328;;;-1:-1:-1;97615:10:0;;-1:-1:-1;97627:3:0;;-1:-1:-1;97632:1:0;;-1:-1:-1;;;96571:1071:0;;;;;;:::o;29326:110::-;29402:26;29412:2;29416:7;29402:26;;;;;;;;;;;;:9;:26::i;:::-;29326:110;;:::o;3450:173::-;3525:6;;;-1:-1:-1;;;;;3542:17:0;;;-1:-1:-1;;;;;;3542:17:0;;;;;;;3575:40;;3525:6;;;3542:17;3525:6;;3575:40;;3506:16;;3575:40;3495:128;3450:173;:::o;27714:315::-;27871:28;27881:4;27887:2;27891:7;27871:9;:28::i;:::-;27918:48;27941:4;27947:2;27951:7;27960:5;27918:22;:48::i;:::-;27910:111;;;;-1:-1:-1;;;27910:111:0;;;;;;;:::i;97650:243::-;97732:4;97758:11;;97754:108;;97826:11;:24;97838:11;97848:1;97838:7;:11;:::i;:::-;97826:24;;;;;;;;;;;;97802:11;:20;97814:7;97802:20;;;;;;;;;;;;:48;;97795:55;;97650:243;;;:::o;97754:108::-;-1:-1:-1;97881:4:0;;97650:243;-1:-1:-1;97650:243:0:o;37939:589::-;-1:-1:-1;;;;;38145:18:0;;38141:187;;38180:40;38212:7;39355:10;:17;;39328:24;;;;:15;:24;;;;;:44;;;39383:24;;;;;;;;;;;;39251:164;38180:40;38141:187;;;38250:2;-1:-1:-1;;;;;38242:10:0;:4;-1:-1:-1;;;;;38242:10:0;;38238:90;;38269:47;38302:4;38308:7;38269:32;:47::i;:::-;-1:-1:-1;;;;;38342:16:0;;38338:183;;38375:45;38412:7;38375:36;:45::i;38338:183::-;38448:4;-1:-1:-1;;;;;38442:10:0;:2;-1:-1:-1;;;;;38442:10:0;;38438:83;;38469:40;38497:2;38501:7;38469:27;:40::i;29663:321::-;29793:18;29799:2;29803:7;29793:5;:18::i;:::-;29844:54;29875:1;29879:2;29883:7;29892:5;29844:22;:54::i;:::-;29822:154;;;;-1:-1:-1;;;29822:154:0;;;;;;;:::i;33063:803::-;33218:4;-1:-1:-1;;;;;33239:13:0;;12435:20;12483:8;33235:624;;33275:72;;-1:-1:-1;;;33275:72:0;;-1:-1:-1;;;;;33275:36:0;;;;;:72;;1304:10;;33326:4;;33332:7;;33341:5;;33275:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;33275:72:0;;;;;;;;-1:-1:-1;;33275:72:0;;;;;;;;;;;;:::i;:::-;;;33271:533;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;33521:13:0;;33517:272;;33564:60;;-1:-1:-1;;;33564:60:0;;;;;;;:::i;33517:272::-;33739:6;33733:13;33724:6;33720:2;33716:15;33709:38;33271:533;-1:-1:-1;;;;;;33398:55:0;-1:-1:-1;;;33398:55:0;;-1:-1:-1;33391:62:0;;33235:624;-1:-1:-1;33843:4:0;33063:803;;;;;;:::o;40042:988::-;40308:22;40358:1;40333:22;40350:4;40333:16;:22::i;:::-;:26;;;;:::i;:::-;40370:18;40391:26;;;:17;:26;;;;;;40308:51;;-1:-1:-1;40524:28:0;;;40520:328;;-1:-1:-1;;;;;40591:18:0;;40569:19;40591:18;;;:12;:18;;;;;;;;:34;;;;;;;;;40642:30;;;;;;:44;;;40759:30;;:17;:30;;;;;:43;;;40520:328;-1:-1:-1;40944:26:0;;;;:17;:26;;;;;;;;40937:33;;;-1:-1:-1;;;;;40988:18:0;;;;;:12;:18;;;;;:34;;;;;;;40981:41;40042:988::o;41325:1079::-;41603:10;:17;41578:22;;41603:21;;41623:1;;41603:21;:::i;:::-;41635:18;41656:24;;;:15;:24;;;;;;42029:10;:26;;41578:46;;-1:-1:-1;41656:24:0;;41578:46;;42029:26;;;;;;:::i;:::-;;;;;;;;;42007:48;;42093:11;42068:10;42079;42068:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;42173:28;;;:15;:28;;;;;;;:41;;;42345:24;;;;;42338:31;42380:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;41396:1008;;;41325:1079;:::o;38829:221::-;38914:14;38931:20;38948:2;38931:16;:20::i;:::-;-1:-1:-1;;;;;38962:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;39007:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;38829:221:0:o;30320:382::-;-1:-1:-1;;;;;30400:16:0;;30392:61;;;;-1:-1:-1;;;30392:61:0;;12738:2:1;30392:61:0;;;12720:21:1;;;12757:18;;;12750:30;12816:34;12796:18;;;12789:62;12868:18;;30392:61:0;12710:182:1;30392:61:0;30473:16;30481:7;30473;:16::i;:::-;30472:17;30464:58;;;;-1:-1:-1;;;30464:58:0;;9252:2:1;30464:58:0;;;9234:21:1;9291:2;9271:18;;;9264:30;-1:-1:-1;;;9310:18:1;;;9303:58;9378:18;;30464:58:0;9224:178:1;30464:58:0;30535:45;30564:1;30568:2;30572:7;30535:20;:45::i;:::-;-1:-1:-1;;;;;30593:13:0;;;;;;:9;:13;;;;;:18;;30610:1;;30593:13;:18;;30610:1;;30593:18;:::i;:::-;;;;-1:-1:-1;;30622:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;30622:21:0;-1:-1:-1;;;;;30622:21:0;;;;;;;;30661:33;;30622:16;;;-1:-1:-1;;;;;;;;;;;30661:33:0;30622:16;;30661:33;30320:382;;:::o;14:247:1:-;73:6;126:2;114:9;105:7;101:23;97:32;94:2;;;142:1;139;132:12;94:2;181:9;168:23;200:31;225:5;200:31;:::i;:::-;250:5;84:177;-1:-1:-1;;;84:177:1:o;526:388::-;594:6;602;655:2;643:9;634:7;630:23;626:32;623:2;;;671:1;668;661:12;623:2;710:9;697:23;729:31;754:5;729:31;:::i;:::-;779:5;-1:-1:-1;836:2:1;821:18;;808:32;849:33;808:32;849:33;:::i;:::-;901:7;891:17;;;613:301;;;;;:::o;919:456::-;996:6;1004;1012;1065:2;1053:9;1044:7;1040:23;1036:32;1033:2;;;1081:1;1078;1071:12;1033:2;1120:9;1107:23;1139:31;1164:5;1139:31;:::i;:::-;1189:5;-1:-1:-1;1246:2:1;1231:18;;1218:32;1259:33;1218:32;1259:33;:::i;:::-;1023:352;;1311:7;;-1:-1:-1;;;1365:2:1;1350:18;;;;1337:32;;1023:352::o;1380:1016::-;1475:6;1483;1491;1499;1552:3;1540:9;1531:7;1527:23;1523:33;1520:2;;;1569:1;1566;1559:12;1520:2;1608:9;1595:23;1627:31;1652:5;1627:31;:::i;:::-;1677:5;-1:-1:-1;1734:2:1;1719:18;;1706:32;1747:33;1706:32;1747:33;:::i;:::-;1799:7;-1:-1:-1;1853:2:1;1838:18;;1825:32;;-1:-1:-1;1908:2:1;1893:18;;1880:32;-1:-1:-1;;;;;1924:30:1;;1921:2;;;1967:1;1964;1957:12;1921:2;1990:22;;2043:4;2035:13;;2031:27;-1:-1:-1;2021:2:1;;2072:1;2069;2062:12;2021:2;2108;2095:16;2133:48;2149:31;2177:2;2149:31;:::i;:::-;2133:48;:::i;:::-;2204:2;2197:5;2190:17;2244:7;2239:2;2234;2230;2226:11;2222:20;2219:33;2216:2;;;2265:1;2262;2255:12;2216:2;2320;2315;2311;2307:11;2302:2;2295:5;2291:14;2278:45;2364:1;2359:2;2354;2347:5;2343:14;2339:23;2332:34;2385:5;2375:15;;;;;1510:886;;;;;;;:::o;2401:416::-;2466:6;2474;2527:2;2515:9;2506:7;2502:23;2498:32;2495:2;;;2543:1;2540;2533:12;2495:2;2582:9;2569:23;2601:31;2626:5;2601:31;:::i;:::-;2651:5;-1:-1:-1;2708:2:1;2693:18;;2680:32;2750:15;;2743:23;2731:36;;2721:2;;2781:1;2778;2771:12;2822:315;2890:6;2898;2951:2;2939:9;2930:7;2926:23;2922:32;2919:2;;;2967:1;2964;2957:12;2919:2;3006:9;2993:23;3025:31;3050:5;3025:31;:::i;:::-;3075:5;3127:2;3112:18;;;;3099:32;;-1:-1:-1;;;2909:228:1:o;3142:245::-;3200:6;3253:2;3241:9;3232:7;3228:23;3224:32;3221:2;;;3269:1;3266;3259:12;3221:2;3308:9;3295:23;3327:30;3351:5;3327:30;:::i;3392:249::-;3461:6;3514:2;3502:9;3493:7;3489:23;3485:32;3482:2;;;3530:1;3527;3520:12;3482:2;3562:9;3556:16;3581:30;3605:5;3581:30;:::i;4195:635::-;4275:6;4328:2;4316:9;4307:7;4303:23;4299:32;4296:2;;;4344:1;4341;4334:12;4296:2;4371:16;;-1:-1:-1;;;;;4399:30:1;;4396:2;;;4442:1;4439;4432:12;4396:2;4465:22;;4518:4;4510:13;;4506:27;-1:-1:-1;4496:2:1;;4547:1;4544;4537:12;4496:2;4576;4570:9;4601:48;4617:31;4645:2;4617:31;:::i;4601:48::-;4672:2;4665:5;4658:17;4712:7;4707:2;4702;4698;4694:11;4690:20;4687:33;4684:2;;;4733:1;4730;4723:12;4684:2;4746:54;4797:2;4792;4785:5;4781:14;4776:2;4772;4768:11;4746:54;:::i;:::-;4819:5;4286:544;-1:-1:-1;;;;;4286:544:1:o;4835:180::-;4894:6;4947:2;4935:9;4926:7;4922:23;4918:32;4915:2;;;4963:1;4960;4953:12;4915:2;-1:-1:-1;4986:23:1;;4905:110;-1:-1:-1;4905:110:1:o;5020:257::-;5061:3;5099:5;5093:12;5126:6;5121:3;5114:19;5142:63;5198:6;5191:4;5186:3;5182:14;5175:4;5168:5;5164:16;5142:63;:::i;:::-;5259:2;5238:15;-1:-1:-1;;5234:29:1;5225:39;;;;5266:4;5221:50;;5069:208;-1:-1:-1;;5069:208:1:o;6017:488::-;-1:-1:-1;;;;;6286:15:1;;;6268:34;;6338:15;;6333:2;6318:18;;6311:43;6385:2;6370:18;;6363:34;;;6433:3;6428:2;6413:18;;6406:31;;;6211:4;;6454:45;;6479:19;;6471:6;6454:45;:::i;:::-;6446:53;6220:285;-1:-1:-1;;;;;;6220:285:1:o;7588:219::-;7737:2;7726:9;7719:21;7700:4;7757:44;7797:2;7786:9;7782:18;7774:6;7757:44;:::i;8224:414::-;8426:2;8408:21;;;8465:2;8445:18;;;8438:30;8504:34;8499:2;8484:18;;8477:62;-1:-1:-1;;;8570:2:1;8555:18;;8548:48;8628:3;8613:19;;8398:240::o;13310:356::-;13512:2;13494:21;;;13531:18;;;13524:30;13590:34;13585:2;13570:18;;13563:62;13657:2;13642:18;;13484:182::o;15183:413::-;15385:2;15367:21;;;15424:2;15404:18;;;15397:30;15463:34;15458:2;15443:18;;15436:62;-1:-1:-1;;;15529:2:1;15514:18;;15507:47;15586:3;15571:19;;15357:239::o;15601:340::-;15803:2;15785:21;;;15842:2;15822:18;;;15815:30;-1:-1:-1;;;15876:2:1;15861:18;;15854:46;15932:2;15917:18;;15775:166::o;16359:342::-;16561:2;16543:21;;;16600:2;16580:18;;;16573:30;-1:-1:-1;;;16634:2:1;16619:18;;16612:48;16692:2;16677:18;;16533:168::o;17294:275::-;17365:2;17359:9;17430:2;17411:13;;-1:-1:-1;;17407:27:1;17395:40;;-1:-1:-1;;;;;17450:34:1;;17486:22;;;17447:62;17444:2;;;17512:18;;:::i;:::-;17548:2;17541:22;17339:230;;-1:-1:-1;17339:230:1:o;17574:186::-;17622:4;-1:-1:-1;;;;;17644:30:1;;17641:2;;;17677:18;;:::i;:::-;-1:-1:-1;17743:2:1;17722:15;-1:-1:-1;;17718:29:1;17749:4;17714:40;;17631:129::o;17765:128::-;17805:3;17836:1;17832:6;17829:1;17826:13;17823:2;;;17842:18;;:::i;:::-;-1:-1:-1;17878:9:1;;17813:80::o;17898:125::-;17938:4;17966:1;17963;17960:8;17957:2;;;17971:18;;:::i;:::-;-1:-1:-1;18008:9:1;;17947:76::o;18028:258::-;18100:1;18110:113;18124:6;18121:1;18118:13;18110:113;;;18200:11;;;18194:18;18181:11;;;18174:39;18146:2;18139:10;18110:113;;;18241:6;18238:1;18235:13;18232:2;;;-1:-1:-1;;18276:1:1;18258:16;;18251:27;18081:205::o;18291:380::-;18370:1;18366:12;;;;18413;;;18434:2;;18488:4;18480:6;18476:17;18466:27;;18434:2;18541;18533:6;18530:14;18510:18;18507:38;18504:2;;;18587:10;18582:3;18578:20;18575:1;18568:31;18622:4;18619:1;18612:15;18650:4;18647:1;18640:15;18504:2;;18346:325;;;:::o;18676:135::-;18715:3;-1:-1:-1;;18736:17:1;;18733:2;;;18756:18;;:::i;:::-;-1:-1:-1;18803:1:1;18792:13;;18723:88::o;18816:127::-;18877:10;18872:3;18868:20;18865:1;18858:31;18908:4;18905:1;18898:15;18932:4;18929:1;18922:15;18948:127;19009:10;19004:3;19000:20;18997:1;18990:31;19040:4;19037:1;19030:15;19064:4;19061:1;19054:15;19080:127;19141:10;19136:3;19132:20;19129:1;19122:31;19172:4;19169:1;19162:15;19196:4;19193:1;19186:15;19212:127;19273:10;19268:3;19264:20;19261:1;19254:31;19304:4;19301:1;19294:15;19328:4;19325:1;19318:15;19344:131;-1:-1:-1;;;;;19419:31:1;;19409:42;;19399:2;;19465:1;19462;19455:12;19480:131;-1:-1:-1;;;;;;19554:32:1;;19544:43;;19534:2;;19601:1;19598;19591:12
Swarm Source
ipfs://90b21747925068e2b95a809dfd2235f6a2462418c2d9737be1b7237b1f8bdc77
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.