// Sources flattened with hardhat v2.0.8 https://hardhat.org
// File @openzeppelin/contracts/math/SignedSafeMath.sol@v3.1.0
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
/**
* @title SignedSafeMath
* @dev Signed math operations with safety checks that revert on error.
*/
library SignedSafeMath {
int256 constant private _INT256_MIN = -2**255;
/**
* @dev Returns the multiplication of two signed integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(int256 a, int256 b) internal pure returns (int256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow");
int256 c = a * b;
require(c / a == b, "SignedSafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two signed integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(int256 a, int256 b) internal pure returns (int256) {
require(b != 0, "SignedSafeMath: division by zero");
require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow");
int256 c = a / b;
return c;
}
/**
* @dev Returns the subtraction of two signed integers, reverting on
* overflow.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(int256 a, int256 b) internal pure returns (int256) {
int256 c = a - b;
require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");
return c;
}
/**
* @dev Returns the addition of two signed integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(int256 a, int256 b) internal pure returns (int256) {
int256 c = a + b;
require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");
return c;
}
}
// File @openzeppelin/contracts/utils/EnumerableMap.sol@v3.1.0
pragma solidity ^0.6.0;
/**
* @dev Library for managing an enumerable variant of Solidity's
* https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
* type.
*
* Maps have the following properties:
*
* - Entries are added, removed, and checked for existence in constant time
* (O(1)).
* - Entries are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableMap for EnumerableMap.UintToAddressMap;
*
* // Declare a set state variable
* EnumerableMap.UintToAddressMap private myMap;
* }
* ```
*
* As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are
* supported.
*/
library EnumerableMap {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Map type with
// bytes32 keys and values.
// The Map implementation uses private functions, and user-facing
// implementations (such as Uint256ToAddressMap) are just wrappers around
// the underlying Map.
// This means that we can only create new EnumerableMaps for types that fit
// in bytes32.
struct MapEntry {
bytes32 _key;
bytes32 _value;
}
struct Map {
// Storage of map keys and values
MapEntry[] _entries;
// Position of the entry defined by a key in the `entries` array, plus 1
// because index 0 means a key is not in the map.
mapping (bytes32 => uint256) _indexes;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {
// We read and store the key's index to prevent multiple reads from the same storage slot
uint256 keyIndex = map._indexes[key];
if (keyIndex == 0) { // Equivalent to !contains(map, key)
map._entries.push(MapEntry({ _key: key, _value: value }));
// The entry is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
map._indexes[key] = map._entries.length;
return true;
} else {
map._entries[keyIndex - 1]._value = value;
return false;
}
}
/**
* @dev Removes a key-value pair from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function _remove(Map storage map, bytes32 key) private returns (bool) {
// We read and store the key's index to prevent multiple reads from the same storage slot
uint256 keyIndex = map._indexes[key];
if (keyIndex != 0) { // Equivalent to contains(map, key)
// To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one
// in the array, and then remove the last entry (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = keyIndex - 1;
uint256 lastIndex = map._entries.length - 1;
// When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.
MapEntry storage lastEntry = map._entries[lastIndex];
// Move the last entry to the index where the entry to delete is
map._entries[toDeleteIndex] = lastEntry;
// Update the index for the moved entry
map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based
// Delete the slot where the moved entry was stored
map._entries.pop();
// Delete the index for the deleted slot
delete map._indexes[key];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function _contains(Map storage map, bytes32 key) private view returns (bool) {
return map._indexes[key] != 0;
}
/**
* @dev Returns the number of key-value pairs in the map. O(1).
*/
function _length(Map storage map) private view returns (uint256) {
return map._entries.length;
}
/**
* @dev Returns the key-value pair stored at position `index` in the map. O(1).
*
* Note that there are no guarantees on the ordering of entries inside the
* array, and it may change when more entries are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {
require(map._entries.length > index, "EnumerableMap: index out of bounds");
MapEntry storage entry = map._entries[index];
return (entry._key, entry._value);
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function _get(Map storage map, bytes32 key) private view returns (bytes32) {
return _get(map, key, "EnumerableMap: nonexistent key");
}
/**
* @dev Same as {_get}, with a custom error message when `key` is not in the map.
*/
function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {
uint256 keyIndex = map._indexes[key];
require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)
return map._entries[keyIndex - 1]._value; // All indexes are 1-based
}
// UintToAddressMap
struct UintToAddressMap {
Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
return _set(map._inner, bytes32(key), bytes32(uint256(value)));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
return _remove(map._inner, bytes32(key));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
return _contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToAddressMap storage map) internal view returns (uint256) {
return _length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the set. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
(bytes32 key, bytes32 value) = _at(map._inner, index);
return (uint256(key), address(uint256(value)));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
return address(uint256(_get(map._inner, bytes32(key))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*/
function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {
return address(uint256(_get(map._inner, bytes32(key), errorMessage)));
}
}
// File @openzeppelin/contracts/GSN/Context.sol@v3.1.0
pragma solidity ^0.6.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN 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 payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
// File @openzeppelin/contracts/introspection/IERC165.sol@v3.1.0
pragma solidity ^0.6.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File @openzeppelin/contracts/token/ERC721/IERC721.sol@v3.1.0
pragma solidity ^0.6.2;
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transfered 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;
}
// File @openzeppelin/contracts/token/ERC721/IERC721Metadata.sol@v3.1.0
pragma solidity ^0.6.2;
/**
* @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);
}
// File @openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol@v3.1.0
pragma solidity ^0.6.2;
/**
* @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);
}
// File @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol@v3.1.0
pragma solidity ^0.6.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
*/
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data)
external returns (bytes4);
}
// File @openzeppelin/contracts/introspection/ERC165.sol@v3.1.0
pragma solidity ^0.6.0;
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts may inherit from this and call {_registerInterface} to declare
* their support of an interface.
*/
contract ERC165 is IERC165 {
/*
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
*/
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
/**
* @dev Mapping of interface ids to whether or not it's supported.
*/
mapping(bytes4 => bool) private _supportedInterfaces;
constructor () internal {
// Derived contracts need only register support for their own interfaces,
// we register support for ERC165 itself here
_registerInterface(_INTERFACE_ID_ERC165);
}
/**
* @dev See {IERC165-supportsInterface}.
*
* Time complexity O(1), guaranteed to always use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
return _supportedInterfaces[interfaceId];
}
/**
* @dev Registers the contract as an implementer of the interface defined by
* `interfaceId`. Support of the actual ERC165 interface is automatic and
* registering its interface id is not required.
*
* See {IERC165-supportsInterface}.
*
* Requirements:
*
* - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
*/
function _registerInterface(bytes4 interfaceId) internal virtual {
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] = true;
}
}
// File @openzeppelin/contracts/math/SafeMath.sol@v3.1.0
pragma solidity ^0.6.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
// File @openzeppelin/contracts/utils/Address.sol@v3.1.0
pragma solidity ^0.6.2;
/**
* @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) {
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line no-inline-assembly
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
/**
* @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");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(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");
return _functionCallWithValue(target, data, value, errorMessage);
}
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
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
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// File @openzeppelin/contracts/utils/EnumerableSet.sol@v3.1.0
pragma solidity ^0.6.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256`
* (`UintSet`) are supported.
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping (bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) { // Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.
bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
require(set._values.length > index, "EnumerableSet: index out of bounds");
return set._values[index];
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(value)));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(value)));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(value)));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint256(_at(set._inner, index)));
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
}
// File @openzeppelin/contracts/utils/Strings.sol@v3.1.0
pragma solidity ^0.6.0;
/**
* @dev String operations.
*/
library Strings {
/**
* @dev Converts a `uint256` to its ASCII `string` 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);
uint256 index = digits - 1;
temp = value;
while (temp != 0) {
buffer[index--] = byte(uint8(48 + temp % 10));
temp /= 10;
}
return string(buffer);
}
}
// File @openzeppelin/contracts/token/ERC721/ERC721.sol@v3.1.0
pragma solidity ^0.6.0;
/**
* @title ERC721 Non-Fungible Token Standard basic implementation
* @dev see https://eips.ethereum.org/EIPS/eip-721
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {
using SafeMath for uint256;
using Address for address;
using EnumerableSet for EnumerableSet.UintSet;
using EnumerableMap for EnumerableMap.UintToAddressMap;
using Strings for uint256;
// Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
// which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
// Mapping from holder address to their (enumerable) set of owned tokens
mapping (address => EnumerableSet.UintSet) private _holderTokens;
// Enumerable mapping from token ids to their owners
EnumerableMap.UintToAddressMap private _tokenOwners;
// Mapping from token ID to approved address
mapping (uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping (address => mapping (address => bool)) private _operatorApprovals;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Optional mapping for token URIs
mapping(uint256 => string) private _tokenURIs;
// Base URI
string private _baseURI;
/*
* bytes4(keccak256('balanceOf(address)')) == 0x70a08231
* bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
* bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
* bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
* bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
* bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
* bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
* bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
* bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
*
* => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
* 0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
*/
bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
/*
* bytes4(keccak256('name()')) == 0x06fdde03
* bytes4(keccak256('symbol()')) == 0x95d89b41
* bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
*
* => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
*/
bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
/*
* bytes4(keccak256('totalSupply()')) == 0x18160ddd
* bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
* bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
*
* => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
*/
bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor (string memory name, string memory symbol) public {
_name = name;
_symbol = symbol;
// register the supported interfaces to conform to ERC721 via ERC165
_registerInterface(_INTERFACE_ID_ERC721);
_registerInterface(_INTERFACE_ID_ERC721_METADATA);
_registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _holderTokens[owner].length();
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view override returns (address) {
return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
// If there is no base URI, return the token URI.
if (bytes(_baseURI).length == 0) {
return _tokenURI;
}
// If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
if (bytes(_tokenURI).length > 0) {
return string(abi.encodePacked(_baseURI, _tokenURI));
}
// If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
return string(abi.encodePacked(_baseURI, tokenId.toString()));
}
/**
* @dev Returns the base URI set via {_setBaseURI}. This will be
* automatically added as a prefix in {tokenURI} to each token's URI, or
* to the token ID if no specific URI is set for that token ID.
*/
function baseURI() public view returns (string memory) {
return _baseURI;
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) {
return _holderTokens[owner].at(index);
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view override returns (uint256) {
// _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds
return _tokenOwners.length();
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view override returns (uint256) {
(uint256 tokenId, ) = _tokenOwners.at(index);
return tokenId;
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view 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 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 mecanisms 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 returns (bool) {
return _tokenOwners.contains(tokenId);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
d*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) 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);
_holderTokens[to].add(tokenId);
_tokenOwners.set(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 = ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
// Clear metadata (if any)
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
_holderTokens[owner].remove(tokenId);
_tokenOwners.remove(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(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);
_holderTokens[from].remove(tokenId);
_holderTokens[to].add(tokenId);
_tokenOwners.set(tokenId, to);
emit Transfer(from, to, tokenId);
}
/**
* @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
/**
* @dev Internal function to set the base URI for all token IDs. It is
* automatically added as a prefix to the value returned in {tokenURI},
* or to the token ID if {tokenURI} is empty.
*/
function _setBaseURI(string memory baseURI_) internal virtual {
_baseURI = baseURI_;
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
private returns (bool)
{
if (!to.isContract()) {
return true;
}
bytes memory returndata = to.functionCall(abi.encodeWithSelector(
IERC721Receiver(to).onERC721Received.selector,
_msgSender(),
from,
tokenId,
_data
), "ERC721: transfer to non ERC721Receiver implementer");
bytes4 retval = abi.decode(returndata, (bytes4));
return (retval == _ERC721_RECEIVED);
}
function _approve(address to, uint256 tokenId) private {
_tokenApprovals[tokenId] = to;
emit Approval(ownerOf(tokenId), to, tokenId);
}
/**
* @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 { }
}
// File @openzeppelin/contracts/access/AccessControl.sol@v3.1.0
pragma solidity ^0.6.0;
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it.
*/
abstract contract AccessControl is Context {
using EnumerableSet for EnumerableSet.AddressSet;
using Address for address;
struct RoleData {
EnumerableSet.AddressSet members;
bytes32 adminRole;
}
mapping (bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view returns (bool) {
return _roles[role].members.contains(account);
}
/**
* @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role.
*/
function getRoleMemberCount(bytes32 role) public view returns (uint256) {
return _roles[role].members.length();
}
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
*
* Role bearers are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
* you perform all queries on the same block. See the following
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information.
*/
function getRoleMember(bytes32 role, uint256 index) public view returns (address) {
return _roles[role].members.at(index);
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) public virtual {
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant");
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) public virtual {
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke");
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) public virtual {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);
_roles[role].adminRole = adminRole;
}
function _grantRole(bytes32 role, address account) private {
if (_roles[role].members.add(account)) {
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) private {
if (_roles[role].members.remove(account)) {
emit RoleRevoked(role, account, _msgSender());
}
}
}
// File @openzeppelin/contracts/utils/Counters.sol@v3.1.0
pragma solidity ^0.6.0;
/**
* @title Counters
* @author Matt Condon (@shrugs)
* @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
* of elements in a mapping, issuing ERC721 ids, or counting request ids.
*
* Include with `using Counters for Counters.Counter;`
* Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}
* overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
* directly accessed.
*/
library Counters {
using SafeMath for uint256;
struct Counter {
// This variable should never be directly accessed by users of the library: interactions must be restricted to
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
// this feature: see https://github.com/ethereum/solidity/issues/4637
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
// The {SafeMath} overflow check can be skipped here, see the comment at the top
counter._value += 1;
}
function decrement(Counter storage counter) internal {
counter._value = counter._value.sub(1);
}
}
// File contracts/structs/TinyBox.sol
pragma solidity ^0.6.4;
struct TinyBox {
uint128 randomness;
uint16 hue;
uint8 saturation;
uint8 lightness;
uint8 shapes;
uint8 hatching;
uint8 widthMin;
uint8 widthMax;
uint8 heightMin;
uint8 heightMax;
uint8 spread;
uint8 grid;
uint8 mirroring;
uint8 bkg; // bkg shade/transparent setting default
uint8 duration; // animation duration default
uint8 options; // 8 boolean values packed - 0th is the animate flag
}
// File contracts/libraries/FixidityLib.sol
pragma solidity ^0.6.8;
/**
* @title FixidityLib
* @author Gadi Guy, Alberto Cuesta Canada
* @notice This library provides fixed point arithmetic with protection against
* overflow.
* All operations are done with int256 and the operands must have been created
* with any of the newFrom* functions, which shift the comma digits() to the
* right and check for limits.
* When using this library be sure of using maxNewFixed() as the upper limit for
* creation of fixed point numbers. Use maxFixedMul(), maxFixedDiv() and
* maxFixedAdd() if you want to be certain that those operations don't
* overflow.
*/
library FixidityLib {
/**
* @notice Number of positions that the comma is shifted to the right.
*/
function digits() public pure returns(uint8) {
return 24;
}
/**
* @notice This is 1 in the fixed point units used in this library.
* @dev Test fixed1() equals 10^digits()
* Hardcoded to 24 digits.
*/
function fixed1() public pure returns(int256) {
return 1000000000000000000000000;
}
/**
* @notice The amount of decimals lost on each multiplication operand.
* @dev Test mulPrecision() equals sqrt(fixed1)
* Hardcoded to 24 digits.
*/
function mulPrecision() public pure returns(int256) {
return 1000000000000;
}
/**
* @notice Maximum value that can be represented in an int256
* @dev Test maxInt256() equals 2^255 -1
*/
function maxInt256() public pure returns(int256) {
return 57896044618658097711785492504343953926634992332820282019728792003956564819967;
}
/**
* @notice Minimum value that can be represented in an int256
* @dev Test minInt256 equals (2^255) * (-1)
*/
function minInt256() public pure returns(int256) {
return -57896044618658097711785492504343953926634992332820282019728792003956564819968;
}
/**
* @notice Maximum value that can be converted to fixed point. Optimize for
* @dev deployment.
* Test maxNewFixed() equals maxInt256() / fixed1()
* Hardcoded to 24 digits.
*/
function maxNewFixed() public pure returns(int256) {
return 57896044618658097711785492504343953926634992332820282;
}
/**
* @notice Maximum value that can be converted to fixed point. Optimize for
* deployment.
* @dev Test minNewFixed() equals -(maxInt256()) / fixed1()
* Hardcoded to 24 digits.
*/
function minNewFixed() public pure returns(int256) {
return -57896044618658097711785492504343953926634992332820282;
}
/**
* @notice Maximum value that can be safely used as an addition operator.
* @dev Test maxFixedAdd() equals maxInt256()-1 / 2
* Test add(maxFixedAdd(),maxFixedAdd()) equals maxFixedAdd() + maxFixedAdd()
* Test add(maxFixedAdd()+1,maxFixedAdd()) throws
* Test add(-maxFixedAdd(),-maxFixedAdd()) equals -maxFixedAdd() - maxFixedAdd()
* Test add(-maxFixedAdd(),-maxFixedAdd()-1) throws
*/
function maxFixedAdd() public pure returns(int256) {
return 28948022309329048855892746252171976963317496166410141009864396001978282409983;
}
/**
* @notice Maximum negative value that can be safely in a subtraction.
* @dev Test maxFixedSub() equals minInt256() / 2
*/
function maxFixedSub() public pure returns(int256) {
return -28948022309329048855892746252171976963317496166410141009864396001978282409984;
}
/**
* @notice Maximum value that can be safely used as a multiplication operator.
* @dev Calculated as sqrt(maxInt256()*fixed1()).
* Be careful with your sqrt() implementation. I couldn't find a calculator
* that would give the exact square root of maxInt256*fixed1 so this number
* is below the real number by no more than 3*10**28. It is safe to use as
* a limit for your multiplications, although powers of two of numbers over
* this value might still work.
* Test multiply(maxFixedMul(),maxFixedMul()) equals maxFixedMul() * maxFixedMul()
* Test multiply(maxFixedMul(),maxFixedMul()+1) throws
* Test multiply(-maxFixedMul(),maxFixedMul()) equals -maxFixedMul() * maxFixedMul()
* Test multiply(-maxFixedMul(),maxFixedMul()+1) throws
* Hardcoded to 24 digits.
*/
function maxFixedMul() public pure returns(int256) {
return 240615969168004498257251713877715648331380787511296;
}
/**
* @notice Maximum value that can be safely used as a dividend.
* @dev divide(maxFixedDiv,newFixedFraction(1,fixed1())) = maxInt256().
* Test maxFixedDiv() equals maxInt256()/fixed1()
* Test divide(maxFixedDiv(),multiply(mulPrecision(),mulPrecision())) = maxFixedDiv()*(10^digits())
* Test divide(maxFixedDiv()+1,multiply(mulPrecision(),mulPrecision())) throws
* Hardcoded to 24 digits.
*/
function maxFixedDiv() public pure returns(int256) {
return 57896044618658097711785492504343953926634992332820282;
}
/**
* @notice Maximum value that can be safely used as a divisor.
* @dev Test maxFixedDivisor() equals fixed1()*fixed1() - Or 10**(digits()*2)
* Test divide(10**(digits()*2 + 1),10**(digits()*2)) = returns 10*fixed1()
* Test divide(10**(digits()*2 + 1),10**(digits()*2 + 1)) = throws
* Hardcoded to 24 digits.
*/
function maxFixedDivisor() public pure returns(int256) {
return 1000000000000000000000000000000000000000000000000;
}
/**
* @notice Converts an int256 to fixed point units, equivalent to multiplying
* by 10^digits().
* @dev Test newFixed(0) returns 0
* Test newFixed(1) returns fixed1()
* Test newFixed(maxNewFixed()) returns maxNewFixed() * fixed1()
* Test newFixed(maxNewFixed()+1) fails
*/
function newFixed(int256 x)
public
pure
returns (int256)
{
assert(x <= maxNewFixed());
assert(x >= minNewFixed());
return x * fixed1();
}
/**
* @notice Converts an int256 in the fixed point representation of this
* library to a non decimal. All decimal digits will be truncated.
*/
function fromFixed(int256 x)
public
pure
returns (int256)
{
return x / fixed1();
}
/**
* @notice Converts an int256 which is already in some fixed point
* representation to a different fixed precision representation.
* Both the origin and destination precisions must be 38 or less digits.
* Origin values with a precision higher than the destination precision
* will be truncated accordingly.
* @dev
* Test convertFixed(1,0,0) returns 1;
* Test convertFixed(1,1,1) returns 1;
* Test convertFixed(1,1,0) returns 0;
* Test convertFixed(1,0,1) returns 10;
* Test convertFixed(10,1,0) returns 1;
* Test convertFixed(10,0,1) returns 100;
* Test convertFixed(100,1,0) returns 10;
* Test convertFixed(100,0,1) returns 1000;
* Test convertFixed(1000,2,0) returns 10;
* Test convertFixed(1000,0,2) returns 100000;
* Test convertFixed(1000,2,1) returns 100;
* Test convertFixed(1000,1,2) returns 10000;
* Test convertFixed(maxInt256,1,0) returns maxInt256/10;
* Test convertFixed(maxInt256,0,1) throws
* Test convertFixed(maxInt256,38,0) returns maxInt256/(10**38);
* Test convertFixed(1,0,38) returns 10**38;
* Test convertFixed(maxInt256,39,0) throws
* Test convertFixed(1,0,39) throws
*/
function convertFixed(int256 x, uint8 _originDigits, uint8 _destinationDigits)
public
pure
returns (int256)
{
assert(_originDigits <= 38 && _destinationDigits <= 38);
uint8 decimalDifference;
if ( _originDigits > _destinationDigits ){
decimalDifference = _originDigits - _destinationDigits;
return x/(uint128(10)**uint128(decimalDifference));
}
else if ( _originDigits < _destinationDigits ){
decimalDifference = _destinationDigits - _originDigits;
// Cast uint8 -> uint128 is safe
// Exponentiation is safe:
// _originDigits and _destinationDigits limited to 38 or less
// decimalDifference = abs(_destinationDigits - _originDigits)
// decimalDifference < 38
// 10**38 < 2**128-1
assert(x <= maxInt256()/uint128(10)**uint128(decimalDifference));
assert(x >= minInt256()/uint128(10)**uint128(decimalDifference));
return x*(uint128(10)**uint128(decimalDifference));
}
// _originDigits == digits())
return x;
}
/**
* @notice Converts an int256 which is already in some fixed point
* representation to that of this library. The _originDigits parameter is the
* precision of x. Values with a precision higher than FixidityLib.digits()
* will be truncated accordingly.
*/
function newFixed(int256 x, uint8 _originDigits)
public
pure
returns (int256)
{
return convertFixed(x, _originDigits, digits());
}
/**
* @notice Converts an int256 in the fixed point representation of this
* library to a different representation. The _destinationDigits parameter is the
* precision of the output x. Values with a precision below than
* FixidityLib.digits() will be truncated accordingly.
*/
function fromFixed(int256 x, uint8 _destinationDigits)
public
pure
returns (int256)
{
return convertFixed(x, digits(), _destinationDigits);
}
/**
* @notice Converts two int256 representing a fraction to fixed point units,
* equivalent to multiplying dividend and divisor by 10^digits().
* @dev
* Test newFixedFraction(maxFixedDiv()+1,1) fails
* Test newFixedFraction(1,maxFixedDiv()+1) fails
* Test newFixedFraction(1,0) fails
* Test newFixedFraction(0,1) returns 0
* Test newFixedFraction(1,1) returns fixed1()
* Test newFixedFraction(maxFixedDiv(),1) returns maxFixedDiv()*fixed1()
* Test newFixedFraction(1,fixed1()) returns 1
* Test newFixedFraction(1,fixed1()-1) returns 0
*/
function newFixedFraction(
int256 numerator,
int256 denominator
)
public
pure
returns (int256)
{
assert(numerator <= maxNewFixed());
assert(denominator <= maxNewFixed());
assert(denominator != 0);
int256 convertedNumerator = newFixed(numerator);
int256 convertedDenominator = newFixed(denominator);
return divide(convertedNumerator, convertedDenominator);
}
/**
* @notice Returns the integer part of a fixed point number.
* @dev
* Test integer(0) returns 0
* Test integer(fixed1()) returns fixed1()
* Test integer(newFixed(maxNewFixed())) returns maxNewFixed()*fixed1()
* Test integer(-fixed1()) returns -fixed1()
* Test integer(newFixed(-maxNewFixed())) returns -maxNewFixed()*fixed1()
*/
function integer(int256 x) public pure returns (int256) {
return (x / fixed1()) * fixed1(); // Can't overflow
}
/**
* @notice Returns the fractional part of a fixed point number.
* In the case of a negative number the fractional is also negative.
* @dev
* Test fractional(0) returns 0
* Test fractional(fixed1()) returns 0
* Test fractional(fixed1()-1) returns 10^24-1
* Test fractional(-fixed1()) returns 0
* Test fractional(-fixed1()+1) returns -10^24-1
*/
function fractional(int256 x) public pure returns (int256) {
return x - (x / fixed1()) * fixed1(); // Can't overflow
}
/**
* @notice Converts to positive if negative.
* Due to int256 having one more negative number than positive numbers
* abs(minInt256) reverts.
* @dev
* Test abs(0) returns 0
* Test abs(fixed1()) returns -fixed1()
* Test abs(-fixed1()) returns fixed1()
* Test abs(newFixed(maxNewFixed())) returns maxNewFixed()*fixed1()
* Test abs(newFixed(minNewFixed())) returns -minNewFixed()*fixed1()
*/
function abs(int256 x) public pure returns (int256) {
if (x >= 0) {
return x;
} else {
int256 result = -x;
assert (result > 0);
return result;
}
}
/**
* @notice x+y. If any operator is higher than maxFixedAdd() it
* might overflow.
* In solidity maxInt256 + 1 = minInt256 and viceversa.
* @dev
* Test add(maxFixedAdd(),maxFixedAdd()) returns maxInt256()-1
* Test add(maxFixedAdd()+1,maxFixedAdd()+1) fails
* Test add(-maxFixedSub(),-maxFixedSub()) returns minInt256()
* Test add(-maxFixedSub()-1,-maxFixedSub()-1) fails
* Test add(maxInt256(),maxInt256()) fails
* Test add(minInt256(),minInt256()) fails
*/
function add(int256 x, int256 y) public pure returns (int256) {
int256 z = x + y;
if (x > 0 && y > 0) assert(z > x && z > y);
if (x < 0 && y < 0) assert(z < x && z < y);
return z;
}
/**
* @notice x-y. You can use add(x,-y) instead.
* @dev Tests covered by add(x,y)
*/
function subtract(int256 x, int256 y) public pure returns (int256) {
return add(x,-y);
}
/**
* @notice x*y. If any of the operators is higher than maxFixedMul() it
* might overflow.
* @dev
* Test multiply(0,0) returns 0
* Test multiply(maxFixedMul(),0) returns 0
* Test multiply(0,maxFixedMul()) returns 0
* Test multiply(maxFixedMul(),fixed1()) returns maxFixedMul()
* Test multiply(fixed1(),maxFixedMul()) returns maxFixedMul()
* Test all combinations of (2,-2), (2, 2.5), (2, -2.5) and (0.5, -0.5)
* Test multiply(fixed1()/mulPrecision(),fixed1()*mulPrecision())
* Test multiply(maxFixedMul()-1,maxFixedMul()) equals multiply(maxFixedMul(),maxFixedMul()-1)
* Test multiply(maxFixedMul(),maxFixedMul()) returns maxInt256() // Probably not to the last digits
* Test multiply(maxFixedMul()+1,maxFixedMul()) fails
* Test multiply(maxFixedMul(),maxFixedMul()+1) fails
*/
function multiply(int256 x, int256 y) public pure returns (int256) {
if (x == 0 || y == 0) return 0;
if (y == fixed1()) return x;
if (x == fixed1()) return y;
// Separate into integer and fractional parts
// x = x1 + x2, y = y1 + y2
int256 x1 = integer(x) / fixed1();
int256 x2 = fractional(x);
int256 y1 = integer(y) / fixed1();
int256 y2 = fractional(y);
// (x1 + x2) * (y1 + y2) = (x1 * y1) + (x1 * y2) + (x2 * y1) + (x2 * y2)
int256 x1y1 = x1 * y1;
if (x1 != 0) assert(x1y1 / x1 == y1); // Overflow x1y1
// x1y1 needs to be multiplied back by fixed1
// solium-disable-next-line mixedcase
int256 fixed_x1y1 = x1y1 * fixed1();
if (x1y1 != 0) assert(fixed_x1y1 / x1y1 == fixed1()); // Overflow x1y1 * fixed1
x1y1 = fixed_x1y1;
int256 x2y1 = x2 * y1;
if (x2 != 0) assert(x2y1 / x2 == y1); // Overflow x2y1
int256 x1y2 = x1 * y2;
if (x1 != 0) assert(x1y2 / x1 == y2); // Overflow x1y2
x2 = x2 / mulPrecision();
y2 = y2 / mulPrecision();
int256 x2y2 = x2 * y2;
if (x2 != 0) assert(x2y2 / x2 == y2); // Overflow x2y2
// result = fixed1() * x1 * y1 + x1 * y2 + x2 * y1 + x2 * y2 / fixed1();
int256 result = x1y1;
result = add(result, x2y1); // Add checks for overflow
result = add(result, x1y2); // Add checks for overflow
result = add(result, x2y2); // Add checks for overflow
return result;
}
/**
* @notice 1/x
* @dev
* Test reciprocal(0) fails
* Test reciprocal(fixed1()) returns fixed1()
* Test reciprocal(fixed1()*fixed1()) returns 1 // Testing how the fractional is truncated
* Test reciprocal(2*fixed1()*fixed1()) returns 0 // Testing how the fractional is truncated
*/
function reciprocal(int256 x) public pure returns (int256) {
assert(x != 0);
return (fixed1()*fixed1()) / x; // Can't overflow
}
/**
* @notice x/y. If the dividend is higher than maxFixedDiv() it
* might overflow. You can use multiply(x,reciprocal(y)) instead.
* There is a loss of precision on division for the lower mulPrecision() decimals.
* @dev
* Test divide(fixed1(),0) fails
* Test divide(maxFixedDiv(),1) = maxFixedDiv()*(10^digits())
* Test divide(maxFixedDiv()+1,1) throws
* Test divide(maxFixedDiv(),maxFixedDiv()) returns fixed1()
*/
function divide(int256 x, int256 y) public pure returns (int256) {
if (y == fixed1()) return x;
assert(y != 0);
assert(y <= maxFixedDivisor());
return multiply(x, reciprocal(y));
}
}
// File contracts/libraries/Utils.sol
pragma solidity ^0.6.4;
library Utils {
using SignedSafeMath for int256;
using Strings for *;
function stringToUint(string memory s)
internal
pure
returns (uint256 result)
{
bytes memory b = bytes(s);
uint256 i;
result = 0;
for (i = 0; i < b.length; i++) {
uint256 c = uint256(uint8(b[i]));
if (c >= 48 && c <= 57) {
result = result * 10 + (c - 48);
}
}
}
// special toString for signed ints
function toString(int256 val) public pure returns (string memory out) {
out = (val < 0) ?
string(abi.encodePacked("-", uint256(val.mul(-1)).toString())) :
uint256(val).toString();
}
function zeroPad(int256 value, uint256 places) internal pure returns (string memory out) {
out = toString(value);
for (uint i=(places-1); i>0; i--)
if (value < int256(10**i))
out = string(abi.encodePacked("0", out));
}
}
// File contracts/libraries/Random.sol
pragma solidity ^0.6.4;
library Random {
using SafeMath for uint256;
using SignedSafeMath for int256;
/**
* Initialize the pool with the entropy of the blockhashes of the num of blocks starting from 0
* The argument "seed" allows you to select a different sequence of random numbers for the same block range.
*/
function init(
uint256 seed
) internal view returns (bytes32[] memory) {
uint256 blocks = 2;
bytes32[] memory pool = new bytes32[](3);
bytes32 salt = keccak256(abi.encodePacked(uint256(0), seed));
for (uint256 i = 0; i < blocks; i++) {
// Add some salt to each blockhash
pool[i + 1] = keccak256(
abi.encodePacked(blockhash(i), salt)
);
}
return pool;
}
/**
* Advances to the next 256-bit random number in the pool of hash chains.
*/
function next(bytes32[] memory pool) internal pure returns (uint256) {
require(pool.length > 1, "Random.next: invalid pool");
uint256 roundRobinIdx = (uint256(pool[0]) % (pool.length - 1)) + 1;
bytes32 hash = keccak256(abi.encodePacked(pool[roundRobinIdx]));
pool[0] = bytes32(uint256(pool[0]) + 1);
pool[roundRobinIdx] = hash;
return uint256(hash);
}
/**
* Produces random integer values, uniformly distributed on the closed interval [a, b]
*/
function uniform(
bytes32[] memory pool,
int256 a,
int256 b
) internal pure returns (int256) {
require(a <= b, "Random.uniform: invalid interval");
return int256(next(pool) % uint256(b - a + 1)) + a;
}
/**
* Produces random integer values, with weighted distributions for values in a set
*/
function weighted(
bytes32[] memory pool,
uint8[7] memory thresholds,
uint16 total
) internal pure returns (uint8) {
int256 p = uniform(pool, 1, total);
int256 s = 0;
for (uint8 i=0; i<7; i++) {
s = s.add(thresholds[i]);
if (p <= s) return i;
}
}
/**
* Produces random integer values, with weighted distributions for values in a set
*/
function weighted(
bytes32[] memory pool,
uint8[24] memory thresholds,
uint16 total
) internal pure returns (uint8) {
int256 p = uniform(pool, 1, total);
int256 s = 0;
for (uint8 i=0; i<24; i++) {
s = s.add(thresholds[i]);
if (p <= s) return i;
}
}
}
// File contracts/TinyBoxesBase.sol
pragma solidity ^0.6.8;
pragma experimental ABIEncoderV2;
interface RandomizerInt {
function returnValue() external view returns (bytes32);
}
contract TinyBoxesBase is ERC721, AccessControl {
using Counters for Counters.Counter;
using Random for bytes32[];
Counters.Counter public _tokenIds;
Counters.Counter public _tokenPromoIds;
RandomizerInt entropySource;
// set contract config constants
address payable skyfly = 0x7A832c86002323a5de3a317b3281Eb88EC3b2C00;
address payable natealex = 0x63a9dbCe75413036B2B778E670aaBd4493aAF9F3;
uint256 public constant price = 100000000000000000; // in wei - 0.1 ETH
uint256 public constant referalPercent = 10;
uint256 public constant referalNewPercent = 15;
uint256 UINT_MAX = uint256(-1);
uint256 MAX_PROMOS = 100;
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); // define the admin role identifier
uint16 public constant TOKEN_LIMIT = 2222;
uint8 public constant ANIMATION_COUNT = 24;
uint8 public constant SCHEME_COUNT = 11;
uint8 public constant avgBlockTime = 14; // avg time per block mined in seconds
uint16 public constant phaseLen = TOKEN_LIMIT / SCHEME_COUNT; // token count per phase
uint32 public constant phaseCountdownTime = 6 hours; // time to pause between phases
// set dynamic contract config
bool public paused = true;
uint256 public blockStart; // next block that minting will start on, countdown end point
uint256 public phaseCountdown = uint256(phaseCountdownTime / avgBlockTime); // blocks to pause between phases
string public contractURI = "https://tinybox.shop/TinyBoxes.json";
// mapping to store all the boxes info
mapping(uint256 => TinyBox) internal boxes;
event SettingsChanged(uint8[3] settings);
/**
* @dev Contract constructor.
* @notice Constructor inherits ERC721
*/
constructor(address entropySourceAddress) public ERC721("TinyBoxes", "[#][#]") {
_setupRole(ADMIN_ROLE, msg.sender);
entropySource = RandomizerInt(entropySourceAddress);
}
// Require Functions
/**
* @notice only allow acounts of a specified role to call a function
*/
function onlyRole(bytes32 _role) view internal {
// Check that the calling account has the required role
require(hasRole(_role, msg.sender), "DENIED");
}
/**
* @notice check if tokens are sold out
*/
function notSoldOut() view internal {
require(_tokenIds.current() < TOKEN_LIMIT, "SOLD OUT");
}
/**
* @notice check if minting is paused
*/
function notPaused() view internal {
require(!paused, "Paused");
}
/**
* @notice check if minting is waiting for a countdown
*/
function notCountdown() view internal {
require(block.number >= blockStart, "WAIT");
}
// Store Mgmt. Functions
/**
* @dev pause minting
*/
function setPause(bool state) external {
onlyRole(ADMIN_ROLE);
paused = state;
}
/**
* @dev set start block for next phase
*/
function startCountdown(uint256 startBlock) external {
onlyRole(ADMIN_ROLE);
require(startBlock > block.number,"Must be future block");
blockStart = startBlock;
paused = false;
}
// Randomizer functions
/**
* @dev set Randomizer
*/
function setRandom(address rand) external {
onlyRole(ADMIN_ROLE);
entropySource = RandomizerInt(rand);
}
/**
* @dev test Randomizer
*/
function testRandom() external view returns (bytes32) {
onlyRole(ADMIN_ROLE);
return entropySource.returnValue();
}
/**
* @dev Call the Randomizer and get some randomness
*/
function getRandomness(uint256 id, uint256 seed)
internal view returns (uint128 randomnesss)
{
uint256 randomness = uint256(keccak256(abi.encodePacked(
entropySource.returnValue(),
id,
seed
))); // mix local and Randomizer entropy for the box randomness
return uint128(randomness % (2**128)); // cut off half the bits
}
// Metadata URI Functions
/**
* @dev Set the tokens URI
* @param _id of a token to update
* @param _uri for the token
* @dev Only the admin can call this
*/
function setTokenURI(uint256 _id, string calldata _uri) external {
onlyRole(ADMIN_ROLE);
_setTokenURI(_id, _uri);
}
/**
* @dev Update the base URI field
* @param _uri base for all tokens
* @dev Only the admin can call this
*/
function setBaseURI(string calldata _uri) external {
onlyRole(ADMIN_ROLE);
_setBaseURI(_uri);
}
/**
* @dev Update the contract URI field
* @dev Only the admin can call this
*/
function setContractURI(string calldata _uri) external {
onlyRole(ADMIN_ROLE);
contractURI = _uri;
}
// Utility Functions
/**
* @dev check current phase
*/
function currentPhase() public view returns (uint8) {
return uint8(_tokenIds.current().div(phaseLen));
}
/**
* @dev calculate the true id for the limited editions
*/
function trueID(uint256 id) public pure returns (int8) {
return int8(int256(id));
}
/**
* @dev check if id is one of limited editions
* @param id of token to check
*/
function isTokenLE(uint256 id) public view returns (bool) {
return id > UINT_MAX - MAX_PROMOS;
}
// Token Info - Data & Settings
/**
* @dev Lookup all token data in one call
* @param _id for which we want token data
* @return randomness of the token
* @return animation of token
* @return shapes of token
* @return hatching of token
* @return size of token
* @return spacing of token
* @return mirroring of token
* @return color for palette root
* @return contrast of the palette
* @return shades for palette
* @return scheme for palette
*/
function tokenData(uint256 _id)
external
view
returns (
uint128 randomness,
uint256 animation,
uint8 shapes,
uint8 hatching,
uint8[4] memory size,
uint8[2] memory spacing,
uint8 mirroring,
uint16[3] memory color,
uint8 contrast,
uint8 shades,
uint8 scheme
)
{
TinyBox memory box = boxes[_id];
uint8[4] memory parts = calcedParts(box, _id);
animation = parts[0];
scheme = parts[1];
shades = parts[2];
contrast = parts[3];
randomness = box.randomness;
mirroring = box.mirroring;
shapes = box.shapes;
hatching = box.hatching;
color = [box.hue, box.saturation, box.lightness];
size = [box.widthMin, box.widthMax, box.heightMin, box.heightMax];
spacing = [box.spread, box.grid];
}
/**
* @dev read the dynamic rendering settings of a token
* @param id of the token to fetch settings for
*/
function readSettings(uint256 id) external view returns (uint8 bkg, uint8 duration, uint8 options) {
TinyBox memory box = boxes[id];
bkg = box.bkg;
duration = box.duration;
options = box.options;
}
/**
* @dev set the dynamic rendering options of a token
* @param id of the token to update
* @param settings new settings values
*/
function changeSettings(uint256 id, uint8[3] calldata settings) external {
require(msg.sender == ownerOf(id) || msg.sender == getApproved(id), "Insuf. Permissions");
require(settings[0] <= 101, "Invalid Bkg");
require(settings[1] > 0, "Invalid Duration");
boxes[id].bkg = settings[0];
boxes[id].duration = settings[1];
boxes[id].options = settings[2];
emit SettingsChanged(settings);
}
/**
* @dev Calculate the randomized and phased values
*/
function calcedParts(TinyBox memory box, uint256 id) internal view returns (uint8[4] memory parts)
{
if (id < TOKEN_LIMIT) { // Normal Tokens
bytes32[] memory pool = Random.init(box.randomness);
uint8[7] memory shadesBins = [4,6,9,6,4,2,1];
uint8[24] memory animationBins = [
175, // Snap Spin 90
200, // Snap Spin 180
175, // Snap Spin 270
160, // Snap Spin Tri
150, // Snap Spin Quad
140, // Snap Spin Tetra
95, // Spin
100, // Slow Mo
90, // Clockwork
20, // Spread
10, // Staggered Spread
80, // Jitter
75, // Giggle
85, // Jolt
110, // Grow n Shrink
105, // Squash n Stretch
50, // Round
90, // Glide
70, // Wave
40, // Fade
140, // Skew X
130, // Skew Y
100, // Stretch
110 // Jello
];
// Generate Random parts from the tokens randomness
parts[0] = uint8(pool.weighted(animationBins, 2500)); // animation
parts[1] = uint8(id.div(phaseLen)); // scheme
parts[2] = uint8(uint256(pool.weighted(shadesBins, 32)).add(1)); //, shades
parts[3] = uint8(pool.uniform(0, box.lightness)); // contrast
} else { // Limited Editions
// Set the parts directly from packed values in the randomness
// Anim(5), Scheme(4), Shades(3), Contrast(7) & Vanity Rand String(17xASCII(7))
parts[0] = uint8(box.randomness / 2**123); // animation
parts[1] = uint8((box.randomness / 2**119) % 2**4); // scheme
parts[2] = uint8((box.randomness / 2**116) % 2**3); //, shades
parts[3] = uint8((box.randomness / 2**109) % 2**7); // contrast
}
}
/**
* @dev Validate the parameters for the docs
*/
function validateParams(uint8 shapes, uint8 hatching, uint16[3] memory color, uint8[4] memory size, uint8[2] memory position, bool exclusive) public pure {
require(shapes > 0 && shapes < 31, "invalid shape count");
require(hatching <= shapes, "invalid hatching");
require(color[2] <= 360, "invalid color");
require(color[1] <= 100, "invalid saturation");
if (!exclusive) require(color[1] >= 20, "invalid saturation");
require(color[2] <= 100, "invalid lightness");
require(size[0] <= size[1], "invalid width range");
require(size[2] <= size[3], "invalid height range");
require(position[0] <= 100, "invalid spread");
}
}
// File contracts/TinyBoxesStore.sol
pragma solidity ^0.6.8;
contract TinyBoxesStore is TinyBoxesBase {
using SafeMath for uint256;
using SignedSafeMath for int256;
using Utils for *;
event RedeemedLE(address by, uint256 id);
/**
* @dev Contract constructor.
*/
constructor(address entropySourceAddress)
public
TinyBoxesBase(entropySourceAddress)
{}
// Payment Functions
/**
* @dev receive direct ETH transfers
* @notice for splitting royalties
*/
receive() external payable {
_splitFunds(msg.value);
}
/**
* @dev withdraw any funds leftover in contract
*/
function withdraw() external {
onlyRole(ADMIN_ROLE);
msg.sender.transfer(address(this).balance);
}
/**
* @dev Split payments
*/
function _splitFunds(uint256 amount) internal {
if (amount > 0) {
uint256 partA = amount.mul(60).div(100);
skyfly.transfer(partA);
natealex.transfer(amount.sub(partA));
}
}
/**
* @dev handle the payment for tokens
*/
function handlePayment(uint256 referalID, address recipient) internal {
// check for suficient payment
require(msg.value >= price, "insuficient payment");
// give the buyer change
if (msg.value > price) msg.sender.transfer(msg.value.sub(price));
// lookup the referer by the referal token id owner
address payable referer = _exists(referalID) ? payable(ownerOf(referalID)) : tx.origin;
// give a higher percent for refering a new user
uint256 percent = (balanceOf(tx.origin) == 0) ? referalNewPercent : referalPercent;
// referer can't be sender or reciever - no self referals
uint256 referal = (referer != msg.sender && referer != tx.origin && referer != recipient) ?
price.mul(percent).div(100) : 0;
// pay referal percentage
if (referal > 0) referer.transfer(referal);
// split remaining payment
_splitFunds(price.sub(referal));
}
/**
* @dev Check if a TinyBox Promo Token is unredeemed
* @param id of the token to check
*/
function unredeemed(uint256 id) public view returns (bool) {
return boxes[id].shapes == 0;
}
// Token Creation Functions
/**
* @dev Create a new LimitedEdition TinyBox Token
* @param recipient of the new LE TinyBox token
*/
function mintLE(address recipient) external {
onlyRole(ADMIN_ROLE);
require(_tokenPromoIds.current() < MAX_PROMOS, "NO MORE");
uint256 id = UINT_MAX - _tokenPromoIds.current();
_safeMint(recipient, id); // mint the new token to the recipient address
_tokenPromoIds.increment();
}
/**
* @dev Create a new TinyBox Token
* @param _seed of token
* @param shapes count and hatching mod value
* @param color settings (hue, sat, light, contrast, shades)
* @param size range for boxes
* @param spacing grid and spread params
* @param recipient of the token
* @return id of the new token
*/
function create(
string calldata _seed,
uint8[2] calldata shapes,
uint16[3] calldata color,
uint8[4] calldata size,
uint8[2] calldata spacing,
uint8 mirroring,
address recipient,
uint256 referalID
) external payable returns (uint256) {
notSoldOut();
notPaused();
notCountdown();
handlePayment(referalID, recipient);
// check box parameters
validateParams(shapes[0], shapes[1], color, size, spacing, false);
// make sure caller is never the 0 address
require(recipient != address(0), "0x00 Recipient Invalid");
// check payment and give change
(referalID, recipient);
// get next id & increment the counter for the next callhandlePayment
uint256 id = _tokenIds.current();
_tokenIds.increment();
// check if its time to pause for next phase countdown
if (_tokenIds.current().mod(phaseLen) == 0)
blockStart = block.number.add(phaseCountdown.mul(currentPhase()));
// add block number and new token id to the seed value
uint256 seed = _seed.stringToUint();
// request randomness
uint128 rand = getRandomness(id, seed);
// create a new box object in storage
boxes[id] = TinyBox({
randomness: rand,
hue: color[0],
saturation: (rand % 200 == 0) ? uint8(0) : uint8(color[1]), // 0.5% chance of grayscale
lightness: uint8(color[2]),
shapes: shapes[0],
hatching: shapes[1],
widthMin: size[0],
widthMax: size[1],
heightMin: size[2],
heightMax: size[3],
spread: spacing[0],
grid: spacing[1],
mirroring: mirroring,
bkg: 0,
duration: 10,
options: 1
});
_safeMint(recipient, id); // mint the new token to the recipient address
}
/**
* @dev Create a Limited Edition TinyBox Token from a Promo token
* @param seed for the token
* @param shapes count and hatching mod value
* @param color settings (hue, sat, light, contrast, shades)
* @param size range for boxes
* @param spacing grid and spread params
*/
function redeemLE(
uint128 seed,
uint8[2] calldata shapes,
uint16[3] calldata color,
uint8[4] calldata size,
uint8[2] calldata spacing,
uint8 mirroring,
uint256 id
) external {
notPaused();
// check owner is caller
require(ownerOf(id) == msg.sender, "NOPE");
// check token is unredeemed
require(unredeemed(id), "USED");
// check box parameters are valid
validateParams(shapes[0], shapes[1], color, size, spacing, true);
// create a new box object
boxes[id] = TinyBox({
randomness: uint128(seed),
hue: color[0],
saturation: uint8(color[1]),
lightness: uint8(color[2]),
shapes: shapes[0],
hatching: shapes[1],
widthMin: size[0],
widthMax: size[1],
heightMin: size[2],
heightMax: size[3],
spread: spacing[0],
grid: spacing[1],
mirroring: mirroring,
bkg: 0,
duration: 10,
options: 1
});
emit RedeemedLE(msg.sender, id);
}
}
// File contracts/TinyBoxes.sol
pragma solidity ^0.6.8;
interface Renderer {
function perpetualRenderer(
TinyBox calldata box,
uint256 id,
address owner,
uint8[4] calldata dVals,
string calldata _slot
) external view returns (string memory);
}
contract TinyBoxes is TinyBoxesStore {
Renderer renderer;
/**
* @dev Contract constructor.
* @notice Constructor inherits from TinyBoxesStore
*/
constructor(address rand, address _renderer)
public
TinyBoxesStore(rand)
{
renderer = Renderer(_renderer);
}
/**
* @dev update the Renderer to a new contract
*/
function updateRenderer(address _renderer) external {
onlyRole(ADMIN_ROLE);
renderer = Renderer(_renderer);
}
/**
* @dev Generate the token SVG art
* @param _id for which we want art
* @return SVG art of token
*/
function tokenArt(uint256 _id)
external
view
returns (string memory)
{
TinyBox memory box = boxes[_id];
return renderer.perpetualRenderer(box, _id, ownerOf(_id), calcedParts(box, _id), "");
}
/**
* @dev Generate the token SVG art with specific options
* @param _id for which we want art
* @param bkg for the token
* @param duration animation duration modifier
* @param options bits - 0th is the animate switch to turn on or off animation
* @param slot string for embeding custom additions
* @return animated SVG art of token
*/
function tokenArt(uint256 _id, uint8 bkg, uint8 duration, uint8 options, string calldata slot)
external
view
returns (string memory)
{
TinyBox memory box = boxes[_id];
box.bkg = bkg;
box.options = options;
box.duration = duration;
return renderer.perpetualRenderer(box ,_id, ownerOf(_id), calcedParts(box, _id), slot);
}
/**
* @dev Generate the token SVG art preview for given parameters
* @param seed for renderer RNG
* @param shapes count and hatching mod
* @param color settings (hue, sat, light, contrast, shades)
* @param size for shapes
* @param spacing grid and spread
* @param traits mirroring, scheme, shades, animation
* @param settings adjustable render options - bkg, duration, options
* @param slot string to enter at end of SVG markup
* @return preview SVG art
*/
function renderPreview(
string calldata seed,
uint16[3] calldata color,
uint8[2] calldata shapes,
uint8[4] calldata size,
uint8[2] calldata spacing,
uint8 mirroring,
uint8[3] calldata settings,
uint8[4] calldata traits,
string calldata slot
) external view returns (string memory) {
validateParams(shapes[0], shapes[1], color, size, spacing, true);
TinyBox memory box = TinyBox({
randomness: uint128(seed.stringToUint()),
hue: color[0],
saturation: uint8(color[1]),
lightness: uint8(color[2]),
shapes: shapes[0],
hatching: shapes[1],
widthMin: size[0],
widthMax: size[1],
heightMin: size[2],
heightMax: size[3],
spread: spacing[0],
mirroring: mirroring,
grid: spacing[1],
bkg: settings[0],
duration: settings[1],
options: settings[2]
});
return renderer.perpetualRenderer(box, 0, address(0), traits, slot);
}
}
{
"compilationTarget": {
"browser/TinyBoxesFlattened.sol": "TinyBoxes"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"rand","type":"address"},{"internalType":"address","name":"_renderer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"RedeemedLE","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8[3]","name":"settings","type":"uint8[3]"}],"name":"SettingsChanged","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":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ANIMATION_COUNT","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SCHEME_COUNT","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN_LIMIT","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_tokenIds","outputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_tokenPromoIds","outputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"avgBlockTime","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blockStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint8[3]","name":"settings","type":"uint8[3]"}],"name":"changeSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_seed","type":"string"},{"internalType":"uint8[2]","name":"shapes","type":"uint8[2]"},{"internalType":"uint16[3]","name":"color","type":"uint16[3]"},{"internalType":"uint8[4]","name":"size","type":"uint8[4]"},{"internalType":"uint8[2]","name":"spacing","type":"uint8[2]"},{"internalType":"uint8","name":"mirroring","type":"uint8"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"referalID","type":"uint256"}],"name":"create","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"currentPhase","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"isTokenLE","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"mintLE","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseCountdown","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseCountdownTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phaseLen","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"readSettings","outputs":[{"internalType":"uint8","name":"bkg","type":"uint8"},{"internalType":"uint8","name":"duration","type":"uint8"},{"internalType":"uint8","name":"options","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"seed","type":"uint128"},{"internalType":"uint8[2]","name":"shapes","type":"uint8[2]"},{"internalType":"uint16[3]","name":"color","type":"uint16[3]"},{"internalType":"uint8[4]","name":"size","type":"uint8[4]"},{"internalType":"uint8[2]","name":"spacing","type":"uint8[2]"},{"internalType":"uint8","name":"mirroring","type":"uint8"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"redeemLE","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"referalNewPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referalPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"seed","type":"string"},{"internalType":"uint16[3]","name":"color","type":"uint16[3]"},{"internalType":"uint8[2]","name":"shapes","type":"uint8[2]"},{"internalType":"uint8[4]","name":"size","type":"uint8[4]"},{"internalType":"uint8[2]","name":"spacing","type":"uint8[2]"},{"internalType":"uint8","name":"mirroring","type":"uint8"},{"internalType":"uint8[3]","name":"settings","type":"uint8[3]"},{"internalType":"uint8[4]","name":"traits","type":"uint8[4]"},{"internalType":"string","name":"slot","type":"string"}],"name":"renderPreview","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"state","type":"bool"}],"name":"setPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rand","type":"address"}],"name":"setRandom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"string","name":"_uri","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startBlock","type":"uint256"}],"name":"startCountdown","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":[],"name":"testRandom","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint8","name":"bkg","type":"uint8"},{"internalType":"uint8","name":"duration","type":"uint8"},{"internalType":"uint8","name":"options","type":"uint8"},{"internalType":"string","name":"slot","type":"string"}],"name":"tokenArt","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"tokenArt","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":"uint256","name":"_id","type":"uint256"}],"name":"tokenData","outputs":[{"internalType":"uint128","name":"randomness","type":"uint128"},{"internalType":"uint256","name":"animation","type":"uint256"},{"internalType":"uint8","name":"shapes","type":"uint8"},{"internalType":"uint8","name":"hatching","type":"uint8"},{"internalType":"uint8[4]","name":"size","type":"uint8[4]"},{"internalType":"uint8[2]","name":"spacing","type":"uint8[2]"},{"internalType":"uint8","name":"mirroring","type":"uint8"},{"internalType":"uint16[3]","name":"color","type":"uint16[3]"},{"internalType":"uint8","name":"contrast","type":"uint8"},{"internalType":"uint8","name":"shades","type":"uint8"},{"internalType":"uint8","name":"scheme","type":"uint8"}],"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":"uint256","name":"id","type":"uint256"}],"name":"trueID","outputs":[{"internalType":"int8","name":"","type":"int8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unredeemed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_renderer","type":"address"}],"name":"updateRenderer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"shapes","type":"uint8"},{"internalType":"uint8","name":"hatching","type":"uint8"},{"internalType":"uint16[3]","name":"color","type":"uint16[3]"},{"internalType":"uint8[4]","name":"size","type":"uint8[4]"},{"internalType":"uint8[2]","name":"position","type":"uint8[2]"},{"internalType":"bool","name":"exclusive","type":"bool"}],"name":"validateParams","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]