ERC-20
Source Code
Overview
Max Total Supply
0 POD
Holders
0
Transfers
-
0
Market
Onchain Market Cap
-
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 0 Decimals)
Loading...
Loading
Loading...
Loading
Loading...
Loading
| # | Exchange | Pair | Price | 24H Volume | % Volume |
|---|
Contract Name:
OpenSeaFactoryImpl
Compiler Version
v0.8.7+commit.e28d00a7
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
import "../interfaces/ERC165Spec.sol";
import "../interfaces/ERC721Spec.sol";
import "../interfaces/AletheaERC721Spec.sol";
import "../lib/StringUtils.sol";
import "../utils/AccessControl.sol";
/**
* @title OpenSea ERC721 Factory interface
*
* @notice In order to mint items only when they're purchased, OpenSea provides a Factory interface
* that is used to define how the items will be minted.
* See https://docs.opensea.io/docs/2-custom-item-sale-contract
*
* @notice This is a generic factory contract that can be used to mint tokens. The configuration
* for minting is specified by an _optionId, which can be used to delineate various
* ways of minting.
*
* @dev Copy of the OpenSea interface:
* https://github.com/ProjectOpenSea/opensea-creatures/blob/master/contracts/IFactoryERC721.sol
*/
interface OpenSeaFactoryERC721 is ERC165 {
/**
* @dev Returns the name of this factory.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol for this factory.
*/
function symbol() external view returns (string memory);
/**
* @dev Number of options the factory supports.
*/
function numOptions() external view returns (uint256);
/**
* @dev Returns whether the option ID can be minted. Can return false if the developer wishes to
* restrict a total supply per option ID (or overall).
*/
function canMint(uint256 _optionId) external view returns (bool);
/**
* @dev Returns a URL specifying some metadata about the option. This metadata can be of the
* same structure as the ERC721 metadata.
*/
function tokenURI(uint256 _optionId) external view returns (string memory);
/**
* @dev Indicates that this is a factory contract. Ideally would use EIP 165 supportsInterface()
*/
function supportsFactoryInterface() external view returns (bool);
/**
* @dev Mints asset(s) in accordance to a specific address with a particular "option". This should be
* callable only by the contract owner or the owner's Wyvern Proxy (later universal login will solve this).
* Options should also be delineated 0 - (numOptions() - 1) for convenient indexing.
* @param _optionId the option id
* @param _toAddress address of the future owner of the asset(s)
*/
function mint(uint256 _optionId, address _toAddress) external;
}
/**
* @dev An OpenSea delegate proxy interface which we use in ProxyRegistry.
* We use it to give compiler a hint that ProxyRegistry.proxies() needs to be
* converted to the address type explicitly
*/
interface OwnableDelegateProxy {}
/**
* @dev OpenSea Proxy Registry determines which address (wrapped as OwnableDelegateProxy)
* is allowed to mint an option at any given time
* @dev OpenSea takes care to set it properly when an option is being bought
*/
interface ProxyRegistry {
/**
* @dev Maps owner address => eligible option minter address wrapped as OwnableDelegateProxy
*/
function proxies(address) external view returns(OwnableDelegateProxy);
}
/**
* @title OpenSea ERC721 Factory implementation
*
* @notice OpenSea Factory interface implementation, NFT minter contract,
* powers the OpenSea sale of the 9,900 personalities of the 10k sale campaign
*
* @dev Links to PersonalityPodERC721 smart contract on deployment, allows OpenSea to mint
* PersonalityPodERC721 from 101 to 10,000 (both bounds inclusive)
*
* @dev Each OpenSea Factory option ID is used to signify the minting of one random type of
* Personality Pod
*/
contract OpenSeaFactoryImpl is OpenSeaFactoryERC721, AccessControl {
/**
* @dev OpenSea expects Factory to be "Ownable", that is having an "owner",
* we introduce a fake "owner" here with no authority
*/
address public owner;
/**
* @dev NFT ERC721 contract address to mint NFTs from and bind to iNFTs created
*/
address public immutable nftContract;
/**
* @dev OpenSea Proxy Registry determines which address is allowed to mint
* an option at any given time
* @dev OpenSea takes care to set it to the NFT buyer address when they buy an option
*/
address public immutable proxyRegistry;
/**
* @dev Number of options the factory supports,
* options start from zero and end at `options` (exclusive)
*/
uint32 private options;
/**
* @dev Base URI is used to construct option URI as
* `base URI + option ID`
*
* @dev For example, if base URI is https://api.com/option/, then option #1
* will have an URI https://api.com/option/1
*/
string public baseURI = "";
/**
* @dev Initialized with the tokenId each optionId should start minting from,
* incremented each time the option is minted
*
* @dev For each option, [currentTokenId[optionId], tokenIdUpperBound[optionId])
* is the range of token IDs left to be minted
*
* @dev Maps optionId => next available (current) token ID for an option
*/
mapping(uint256 => uint256) public currentTokenId;
/**
* @dev At what tokenId each optionId should end minting at (exclusive)
*
* @dev For each option, [currentTokenId[optionId], tokenIdUpperBound[optionId])
* is the range of token IDs left to be minted
*
* @dev Maps optionId => final token ID (exclusive) for an option
*/
mapping(uint256 => uint256) public tokenIdUpperBound;
/**
* @notice Minter is responsible for creating (minting) iNFTs
*
* @dev Role ROLE_MINTER allows minting iNFTs (calling `mint` function)
*/
uint32 public constant ROLE_MINTER = 0x0001_0000;
/**
* @notice URI manager is responsible for managing base URI
* which is used to construct URIs for each option
*
* @dev Role ROLE_URI_MANAGER allows updating the base URI
* (executing `setBaseURI` function)
*/
uint32 public constant ROLE_URI_MANAGER = 0x0010_0000;
/**
* @notice OpenSea manager is responsible for registering the factory
* in OpenSea via "Transfer" event mechanism
*
* @dev Role ROLE_OS_MANAGER allows notifying OpenSea about the contract
* "owner" change via emitting "Transfer" events read by the OpenSea
* (executing `fireTransferEvents` function)
*/
uint32 public constant ROLE_OS_MANAGER = 0x0040_0000;
/**
* @dev Fired in mint() when Alethea NFT is created
*
* @param _by an address which executed the mint function
* @param _optionId OpenSea option ID
* @param _to an address NFT was minted to
*/
event Minted(address indexed _by, uint256 _optionId, address indexed _to);
/**
* @dev Fired in setBaseURI()
*
* @param _by an address which executed update
* @param _oldVal old _baseURI value
* @param _newVal new _baseURI value
*/
event BaseURIUpdated(address indexed _by, string _oldVal, string _newVal);
/**
* @dev An event caught by the OpenSea for automatic factory registration
* and assigning option "owner" to `to` address defined in the event
* @dev See: OpenSea docs and source code examples,
* https://docs.opensea.io/docs/2-custom-sale-contract-viewing-your-sale-assets-on-opensea
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Creates/deploys the factory and binds it to NFT smart contract on construction
*
* @param _nft deployed NFT smart contract address; factory will mint NFTs of that type
* @param _proxyRegistry OpenSea proxy registry address
* @param _rangeBounds token ID ranges foreach option - the initial `currentTokenId` and `tokenIdUpperBound`
*/
constructor(address _nft, address _proxyRegistry, uint32[] memory _rangeBounds) {
// verify the inputs are set
require(_nft != address(0), "NFT contract is not set");
require(_proxyRegistry != address(0), "OpenSea proxy registry is not set");
// ensure there is at least one option (2 numbers for 1 range)
require(_rangeBounds.length > 1, "invalid number of options");
// verify range bound initial element is greater than 100
require(_rangeBounds[0] > 100, "invalid range bound initial element");
// verify inputs are valid smart contracts of the expected interfaces
require(ERC165(_nft).supportsInterface(type(ERC721).interfaceId), "unexpected NFT type");
require(ERC165(_nft).supportsInterface(type(ERC721Metadata).interfaceId), "unexpected NFT type");
require(ERC165(_nft).supportsInterface(type(MintableERC721).interfaceId), "unexpected NFT type");
// verify that range bounds elements increase (monotonically increasing)
for(uint256 i = 0; i < _rangeBounds.length - 1; i++) {
// compare current element and next element
require(_rangeBounds[i] < _rangeBounds[i + 1], "invalid range bounds");
}
// assign the NFT address
nftContract = _nft;
// assign owner
owner = msg.sender;
// assign OpenSea Proxy Registry address
proxyRegistry = _proxyRegistry;
// number of options is derived from the range bounds array
options = uint32(_rangeBounds.length - 1);
// assign the appropriate start and upper bound for each optionId
for(uint256 i = 0; i < _rangeBounds.length - 1; i++) {
currentTokenId[i] = _rangeBounds[i];
tokenIdUpperBound[i] = _rangeBounds[i + 1];
}
// fire events for each option
fireTransferEvents(address(0), msg.sender);
}
/**
* @dev Restricted access function which updates base URI for optionIds
*
* @param _baseURI new base URI to set
*/
function setBaseURI(string memory _baseURI) public virtual {
// verify the access permission
require(isSenderInRole(ROLE_URI_MANAGER), "access denied");
// emit an event first - to log both old and new values
emit BaseURIUpdated(msg.sender, baseURI, _baseURI);
// and update base URI
baseURI = _baseURI;
}
/**
* @inheritdoc ERC165
*/
function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {
// reconstruct from current interface and super interface
return interfaceId == type(OpenSeaFactoryERC721).interfaceId;
}
/**
* @inheritdoc OpenSeaFactoryERC721
*/
function name() public override view returns (string memory) {
// delegate to super implementation
return ERC721Metadata(nftContract).name();
}
/**
* @inheritdoc OpenSeaFactoryERC721
*/
function symbol() public override view returns (string memory) {
// delegate to super implementation
return ERC721Metadata(nftContract).symbol();
}
/**
* @inheritdoc OpenSeaFactoryERC721
*/
function numOptions() public override view returns (uint256) {
// calculate based on 0-indexed options
return options;
}
/**
* @inheritdoc OpenSeaFactoryERC721
*/
function canMint(uint256 _optionId) public override view returns (bool) {
// check valid optionId, bounds
return _optionId < options && currentTokenId[_optionId] < tokenIdUpperBound[_optionId];
}
/**
* @inheritdoc OpenSeaFactoryERC721
*/
function tokenURI(uint256 _optionId) public override view returns (string memory) {
// concatenate base URI + token ID
return StringUtils.concat(baseURI, StringUtils.itoa(_optionId, 10));
}
/**
* @inheritdoc OpenSeaFactoryERC721
*/
function supportsFactoryInterface() public override pure returns (bool) {
// use ERC165 supportsInterface to return `true`
return supportsInterface(type(OpenSeaFactoryERC721).interfaceId);
}
/**
* @inheritdoc OpenSeaFactoryERC721
*/
function mint(uint256 _optionId, address _toAddress) public override {
// verify the access permission
require(address(ProxyRegistry(proxyRegistry).proxies(owner)) == msg.sender, "access denied");
// verify option ID can be minted
require(canMint(_optionId), "cannot mint");
// do the mint
MintableERC721(nftContract).mint(_toAddress, currentTokenId[_optionId]);
// emit an event before increasing
emit Minted(msg.sender, currentTokenId[_optionId], _toAddress);
// increment next tokenId
currentTokenId[_optionId]++;
}
/**
* @dev Fires transfer events for each option. Used to change contract "owner"
* See: OpenSea docs and source code examples,
* https://docs.opensea.io/docs/2-custom-sale-contract-viewing-your-sale-assets-on-opensea
*
* @param _from transfer optionIds from
* @param _to transfer optionIds to
*/
function fireTransferEvents(address _from, address _to) public {
// verify the access permission
require(isSenderInRole(ROLE_OS_MANAGER), "access denied");
// fire events for each option
for (uint256 i = 0; i < options; i++) {
emit Transfer(_from, _to, i);
}
}
/**
* Hack to get things to work automatically on OpenSea.
* Use transferFrom so the frontend doesn't have to worry about different method names.
*/
function transferFrom(address _from, address _to, uint256 _tokenId) public {
// simply delegate to `mint`
mint(_tokenId, _to);
}
/**
* Hack to get things to work automatically on OpenSea.
* Use isApprovedForAll so the frontend doesn't have to worry about different method names.
*/
function isApprovedForAll(address _owner, address _operator) public view returns (bool) {
// true if called by contract "owner" which is the token owner itself
if(owner == _owner && _owner == _operator) {
return true;
}
// lookup the registry
return owner == _owner && address(ProxyRegistry(proxyRegistry).proxies(_owner)) == _operator;
}
/**
* Hack to get things to work automatically on OpenSea.
* Use isApprovedForAll so the frontend doesn't have to worry about different method names.
*/
function ownerOf(uint256 _tokenId) public view returns (address _owner) {
// return smart contract "owner"
return owner;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
/**
* @title ERC-165 Standard Interface Detection
*
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* @dev Implementers can declare support of contract interfaces,
* which can then be queried by others.
*
* @author Christian Reitwießner, Nick Johnson, Fabian Vogelsteller, Jordi Baylina, Konrad Feldmeier, William Entriken
*/
interface ERC165 {
/**
* @notice Query if a contract implements an interface
*
* @dev Interface identification is specified in ERC-165.
* This function uses less than 30,000 gas.
*
* @param interfaceID The interface identifier, as specified in ERC-165
* @return `true` if the contract implements `interfaceID` and
* `interfaceID` is not 0xffffffff, `false` otherwise
*/
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
import "./ERC165Spec.sol";
/**
* @title ERC-721 Non-Fungible Token Standard
*
* @notice See https://eips.ethereum.org/EIPS/eip-721
*
* @dev Solidity issue #3412: The ERC721 interfaces include explicit mutability guarantees for each function.
* Mutability guarantees are, in order weak to strong: payable, implicit nonpayable, view, and pure.
* Implementation MUST meet the mutability guarantee in this interface and MAY meet a stronger guarantee.
* For example, a payable function in this interface may be implemented as nonpayable
* (no state mutability specified) in implementing contract.
* It is expected a later Solidity release will allow stricter contract to inherit from this interface,
* but current workaround is that we edit this interface to add stricter mutability before inheriting:
* we have removed all "payable" modifiers.
*
* @dev The ERC-165 identifier for this interface is 0x80ac58cd.
*
* @author William Entriken, Dieter Shirley, Jacob Evans, Nastassia Sachs
*/
interface ERC721 is ERC165 {
/// @dev This emits when ownership of any NFT changes by any mechanism.
/// This event emits when NFTs are created (`from` == 0) and destroyed
/// (`to` == 0). Exception: during contract creation, any number of NFTs
/// may be created and assigned without emitting Transfer. At the time of
/// any transfer, the approved address for that NFT (if any) is reset to none.
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
/// @dev This emits when the approved address for an NFT is changed or
/// reaffirmed. The zero address indicates there is no approved address.
/// When a Transfer event emits, this also indicates that the approved
/// address for that NFT (if any) is reset to none.
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
/// @dev This emits when an operator is enabled or disabled for an owner.
/// The operator can manage all NFTs of the owner.
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
/// @notice Count all NFTs assigned to an owner
/// @dev NFTs assigned to the zero address are considered invalid, and this
/// function throws for queries about the zero address.
/// @param _owner An address for whom to query the balance
/// @return The number of NFTs owned by `_owner`, possibly zero
function balanceOf(address _owner) external view returns (uint256);
/// @notice Find the owner of an NFT
/// @dev NFTs assigned to zero address are considered invalid, and queries
/// about them do throw.
/// @param _tokenId The identifier for an NFT
/// @return The address of the owner of the NFT
function ownerOf(uint256 _tokenId) external view returns (address);
/// @notice Transfers the ownership of an NFT from one address to another address
/// @dev Throws unless `msg.sender` is the current owner, an authorized
/// operator, or the approved address for this NFT. Throws if `_from` is
/// not the current owner. Throws if `_to` is the zero address. Throws if
/// `_tokenId` is not a valid NFT. When transfer is complete, this function
/// checks if `_to` is a smart contract (code size > 0). If so, it calls
/// `onERC721Received` on `_to` and throws if the return value is not
/// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
/// @param _data Additional data with no specified format, sent in call to `_to`
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata _data) external /*payable*/;
/// @notice Transfers the ownership of an NFT from one address to another address
/// @dev This works identically to the other function with an extra data parameter,
/// except this function just sets data to "".
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external /*payable*/;
/// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
/// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
/// THEY MAY BE PERMANENTLY LOST
/// @dev Throws unless `msg.sender` is the current owner, an authorized
/// operator, or the approved address for this NFT. Throws if `_from` is
/// not the current owner. Throws if `_to` is the zero address. Throws if
/// `_tokenId` is not a valid NFT.
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
function transferFrom(address _from, address _to, uint256 _tokenId) external /*payable*/;
/// @notice Change or reaffirm the approved address for an NFT
/// @dev The zero address indicates there is no approved address.
/// Throws unless `msg.sender` is the current NFT owner, or an authorized
/// operator of the current owner.
/// @param _approved The new approved NFT controller
/// @param _tokenId The NFT to approve
function approve(address _approved, uint256 _tokenId) external /*payable*/;
/// @notice Enable or disable approval for a third party ("operator") to manage
/// all of `msg.sender`'s assets
/// @dev Emits the ApprovalForAll event. The contract MUST allow
/// multiple operators per owner.
/// @param _operator Address to add to the set of authorized operators
/// @param _approved True if the operator is approved, false to revoke approval
function setApprovalForAll(address _operator, bool _approved) external;
/// @notice Get the approved address for a single NFT
/// @dev Throws if `_tokenId` is not a valid NFT.
/// @param _tokenId The NFT to find the approved address for
/// @return The approved address for this NFT, or the zero address if there is none
function getApproved(uint256 _tokenId) external view returns (address);
/// @notice Query if an address is an authorized operator for another address
/// @param _owner The address that owns the NFTs
/// @param _operator The address that acts on behalf of the owner
/// @return True if `_operator` is an approved operator for `_owner`, false otherwise
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}
/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.
interface ERC721TokenReceiver {
/// @notice Handle the receipt of an NFT
/// @dev The ERC721 smart contract calls this function on the recipient
/// after a `transfer`. This function MAY throw to revert and reject the
/// transfer. Return of other than the magic value MUST result in the
/// transaction being reverted.
/// Note: the contract address is always the message sender.
/// @param _operator The address which called `safeTransferFrom` function
/// @param _from The address which previously owned the token
/// @param _tokenId The NFT identifier which is being transferred
/// @param _data Additional data with no specified format
/// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
/// unless throwing
function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) external returns(bytes4);
}
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
*
* @notice See https://eips.ethereum.org/EIPS/eip-721
*
* @dev The ERC-165 identifier for this interface is 0x5b5e139f.
*
* @author William Entriken, Dieter Shirley, Jacob Evans, Nastassia Sachs
*/
interface ERC721Metadata is ERC721 {
/// @notice A descriptive name for a collection of NFTs in this contract
function name() external view returns (string memory _name);
/// @notice An abbreviated name for NFTs in this contract
function symbol() external view returns (string memory _symbol);
/// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
/// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
/// 3986. The URI may point to a JSON file that conforms to the "ERC721
/// Metadata JSON Schema".
function tokenURI(uint256 _tokenId) external view returns (string memory);
}
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
*
* @notice See https://eips.ethereum.org/EIPS/eip-721
*
* @dev The ERC-165 identifier for this interface is 0x780e9d63.
*
* @author William Entriken, Dieter Shirley, Jacob Evans, Nastassia Sachs
*/
interface ERC721Enumerable is ERC721 {
/// @notice Count NFTs tracked by this contract
/// @return A count of valid NFTs tracked by this contract, where each one of
/// them has an assigned and queryable owner not equal to the zero address
function totalSupply() external view returns (uint256);
/// @notice Enumerate valid NFTs
/// @dev Throws if `_index` >= `totalSupply()`.
/// @param _index A counter less than `totalSupply()`
/// @return The token identifier for the `_index`th NFT,
/// (sort order not specified)
function tokenByIndex(uint256 _index) external view returns (uint256);
/// @notice Enumerate NFTs assigned to an owner
/// @dev Throws if `_index` >= `balanceOf(_owner)` or if
/// `_owner` is the zero address, representing invalid NFTs.
/// @param _owner An address where we are interested in NFTs owned by them
/// @param _index A counter less than `balanceOf(_owner)`
/// @return The token identifier for the `_index`th NFT assigned to `_owner`,
/// (sort order not specified)
function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
/**
* @title Alethea Mintable ERC721
*
* @notice Defines mint capabilities for Alethea ERC721 tokens.
* This interface should be treated as a definition of what mintable means for ERC721
*/
interface MintableERC721 {
/**
* @notice Checks if specified token exists
*
* @dev Returns whether the specified token ID has an ownership
* information associated with it
*
* @param _tokenId ID of the token to query existence for
* @return whether the token exists (true - exists, false - doesn't exist)
*/
function exists(uint256 _tokenId) external view returns(bool);
/**
* @dev Creates new token with token ID specified
* and assigns an ownership `_to` for this token
*
* @dev Unsafe: doesn't execute `onERC721Received` on the receiver.
* Prefer the use of `saveMint` instead of `mint`.
*
* @dev Should have a restricted access handled by the implementation
*
* @param _to an address to mint token to
* @param _tokenId ID of the token to mint
*/
function mint(address _to, uint256 _tokenId) external;
/**
* @dev Creates new tokens starting with token ID specified
* and assigns an ownership `_to` for these tokens
*
* @dev Token IDs to be minted: [_tokenId, _tokenId + n)
*
* @dev n must be greater or equal 2: `n > 1`
*
* @dev Unsafe: doesn't execute `onERC721Received` on the receiver.
* Prefer the use of `saveMintBatch` instead of `mintBatch`.
*
* @dev Should have a restricted access handled by the implementation
*
* @param _to an address to mint tokens to
* @param _tokenId ID of the first token to mint
* @param n how many tokens to mint, sequentially increasing the _tokenId
*/
function mintBatch(address _to, uint256 _tokenId, uint256 n) external;
/**
* @dev Creates new token with token ID specified
* and assigns an ownership `_to` for this token
*
* @dev Checks if `_to` is a smart contract (code size > 0). If so, it calls
* `onERC721Received` on `_to` and throws if the return value is not
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
*
* @dev Should have a restricted access handled by the implementation
*
* @param _to an address to mint token to
* @param _tokenId ID of the token to mint
*/
function safeMint(address _to, uint256 _tokenId) external;
/**
* @dev Creates new token with token ID specified
* and assigns an ownership `_to` for this token
*
* @dev Checks if `_to` is a smart contract (code size > 0). If so, it calls
* `onERC721Received` on `_to` and throws if the return value is not
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
*
* @dev Should have a restricted access handled by the implementation
*
* @param _to an address to mint token to
* @param _tokenId ID of the token to mint
* @param _data additional data with no specified format, sent in call to `_to`
*/
function safeMint(address _to, uint256 _tokenId, bytes memory _data) external;
/**
* @dev Creates new tokens starting with token ID specified
* and assigns an ownership `_to` for these tokens
*
* @dev Token IDs to be minted: [_tokenId, _tokenId + n)
*
* @dev n must be greater or equal 2: `n > 1`
*
* @dev Checks if `_to` is a smart contract (code size > 0). If so, it calls
* `onERC721Received` on `_to` and throws if the return value is not
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
*
* @dev Should have a restricted access handled by the implementation
*
* @param _to an address to mint token to
* @param _tokenId ID of the token to mint
* @param n how many tokens to mint, sequentially increasing the _tokenId
*/
function safeMintBatch(address _to, uint256 _tokenId, uint256 n) external;
/**
* @dev Creates new tokens starting with token ID specified
* and assigns an ownership `_to` for these tokens
*
* @dev Token IDs to be minted: [_tokenId, _tokenId + n)
*
* @dev n must be greater or equal 2: `n > 1`
*
* @dev Checks if `_to` is a smart contract (code size > 0). If so, it calls
* `onERC721Received` on `_to` and throws if the return value is not
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
*
* @dev Should have a restricted access handled by the implementation
*
* @param _to an address to mint token to
* @param _tokenId ID of the token to mint
* @param n how many tokens to mint, sequentially increasing the _tokenId
* @param _data additional data with no specified format, sent in call to `_to`
*/
function safeMintBatch(address _to, uint256 _tokenId, uint256 n, bytes memory _data) external;
}
/**
* @title Alethea Burnable ERC721
*
* @notice Defines burn capabilities for Alethea ERC721 tokens.
* This interface should be treated as a definition of what burnable means for ERC721
*/
interface BurnableERC721 {
/**
* @notice Destroys the token with token ID specified
*
* @dev Should be accessible publicly by token owners.
* May have a restricted access handled by the implementation
*
* @param _tokenId ID of the token to burn
*/
function burn(uint256 _tokenId) external;
}
/**
* @title With Base URI
*
* @notice A marker interface for the contracts having the baseURI() function
* or public string variable named baseURI
* NFT implementations like TinyERC721, or ShortERC721 are example of such smart contracts
*/
interface WithBaseURI {
/**
* @dev Usually used in NFT implementations to construct ERC721Metadata.tokenURI as
* `base URI + token ID` if token URI is not set (not present in `_tokenURIs` mapping)
*
* @dev For example, if base URI is https://api.com/token/, then token #1
* will have an URI https://api.com/token/1
*/
function baseURI() external view returns(string memory);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
/**
* @title String Utils Library
*
* @dev Library for working with strings, primarily converting
* between strings and integer types
*/
library StringUtils {
/**
* @dev Converts a string to unsigned integer using the specified `base`
* @dev Throws on invalid input
* (wrong characters for a given `base`)
* @dev Throws if given `base` is not supported
* @param a string to convert
* @param base number base, one of 2, 8, 10, 16
* @return i a number representing given string
*/
function atoi(string memory a, uint8 base) internal pure returns (uint256 i) {
// check if the base is valid
require(base == 2 || base == 8 || base == 10 || base == 16);
// convert string into bytes for convenient iteration
bytes memory buf = bytes(a);
// iterate over the string (bytes buffer)
for(uint256 p = 0; p < buf.length; p++) {
// extract the digit
uint8 digit = uint8(buf[p]) - 0x30;
// if digit is greater then 10 - mind the gap
// see `itoa` function for more details
if(digit > 10) {
// remove the gap
digit -= 7;
}
// check if digit meets the base
require(digit < base);
// move to the next digit slot
i *= base;
// add digit to the result
i += digit;
}
// return the result
return i;
}
/**
* @dev Converts a integer to a string using the specified `base`
* @dev Throws if given `base` is not supported
* @param i integer to convert
* @param base number base, one of 2, 8, 10, 16
* @return a a string representing given integer
*/
function itoa(uint256 i, uint8 base) internal pure returns (string memory a) {
// check if the base is valid
require(base == 2 || base == 8 || base == 10 || base == 16);
// for zero input the result is "0" string for any base
if(i == 0) {
return "0";
}
// bytes buffer to put ASCII characters into
bytes memory buf = new bytes(256);
// position within a buffer to be used in cycle
uint256 p = 0;
// extract digits one by one in a cycle
while(i > 0) {
// extract current digit
uint8 digit = uint8(i % base);
// convert it to an ASCII code
// 0x20 is " "
// 0x30-0x39 is "0"-"9"
// 0x41-0x5A is "A"-"Z"
// 0x61-0x7A is "a"-"z" ("A"-"Z" XOR " ")
uint8 ascii = digit + 0x30;
// if digit is greater then 10,
// fix the 0x3A-0x40 gap of punctuation marks
// (7 characters in ASCII table)
if(digit >= 10) {
// jump through the gap
ascii += 7;
}
// write character into the buffer
buf[p++] = bytes1(ascii);
// move to the next digit
i /= base;
}
// `p` contains real length of the buffer now,
// allocate the resulting buffer of that size
bytes memory result = new bytes(p);
// copy the buffer in the reversed order
for(p = 0; p < result.length; p++) {
// copy from the beginning of the original buffer
// to the end of resulting smaller buffer
result[result.length - p - 1] = buf[p];
}
// construct string and return
return string(result);
}
/**
* @dev Concatenates two strings `s1` and `s2`, for example, if
* `s1` == `foo` and `s2` == `bar`, the result `s` == `foobar`
* @param s1 first string
* @param s2 second string
* @return s concatenation result s1 + s2
*/
function concat(string memory s1, string memory s2) internal pure returns (string memory s) {
// an old way of string concatenation (Solidity 0.4) is commented out
/*
// convert s1 into buffer 1
bytes memory buf1 = bytes(s1);
// convert s2 into buffer 2
bytes memory buf2 = bytes(s2);
// create a buffer for concatenation result
bytes memory buf = new bytes(buf1.length + buf2.length);
// copy buffer 1 into buffer
for(uint256 i = 0; i < buf1.length; i++) {
buf[i] = buf1[i];
}
// copy buffer 2 into buffer
for(uint256 j = buf1.length; j < buf2.length; j++) {
buf[j] = buf2[j - buf1.length];
}
// construct string and return
return string(buf);
*/
// simply use built in function
return string(abi.encodePacked(s1, s2));
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
/**
* @title Access Control List
*
* @notice Access control smart contract provides an API to check
* if specific operation is permitted globally and/or
* if particular user has a permission to execute it.
*
* @notice It deals with two main entities: features and roles.
*
* @notice Features are designed to be used to enable/disable specific
* functions (public functions) of the smart contract for everyone.
* @notice User roles are designed to restrict access to specific
* functions (restricted functions) of the smart contract to some users.
*
* @notice Terms "role", "permissions" and "set of permissions" have equal meaning
* in the documentation text and may be used interchangeably.
* @notice Terms "permission", "single permission" implies only one permission bit set.
*
* @notice Access manager is a special role which allows to grant/revoke other roles.
* Access managers can only grant/revoke permissions which they have themselves.
* As an example, access manager with no other roles set can only grant/revoke its own
* access manager permission and nothing else.
*
* @notice Access manager permission should be treated carefully, as a super admin permission:
* Access manager with even no other permission can interfere with another account by
* granting own access manager permission to it and effectively creating more powerful
* permission set than its own.
*
* @dev Both current and OpenZeppelin AccessControl implementations feature a similar API
* to check/know "who is allowed to do this thing".
* @dev Zeppelin implementation is more flexible:
* - it allows setting unlimited number of roles, while current is limited to 256 different roles
* - it allows setting an admin for each role, while current allows having only one global admin
* @dev Current implementation is more lightweight:
* - it uses only 1 bit per role, while Zeppelin uses 256 bits
* - it allows setting up to 256 roles at once, in a single transaction, while Zeppelin allows
* setting only one role in a single transaction
*
* @dev This smart contract is designed to be inherited by other
* smart contracts which require access control management capabilities.
*
* @dev Access manager permission has a bit 255 set.
* This bit must not be used by inheriting contracts for any other permissions/features.
*/
contract AccessControl {
/**
* @notice Access manager is responsible for assigning the roles to users,
* enabling/disabling global features of the smart contract
* @notice Access manager can add, remove and update user roles,
* remove and update global features
*
* @dev Role ROLE_ACCESS_MANAGER allows modifying user roles and global features
* @dev Role ROLE_ACCESS_MANAGER has single bit at position 255 enabled
*/
uint256 public constant ROLE_ACCESS_MANAGER = 0x8000000000000000000000000000000000000000000000000000000000000000;
/**
* @dev Bitmask representing all the possible permissions (super admin role)
* @dev Has all the bits are enabled (2^256 - 1 value)
*/
uint256 private constant FULL_PRIVILEGES_MASK = type(uint256).max; // before 0.8.0: uint256(-1) overflows to 0xFFFF...
/**
* @notice Privileged addresses with defined roles/permissions
* @notice In the context of ERC20/ERC721 tokens these can be permissions to
* allow minting or burning tokens, transferring on behalf and so on
*
* @dev Maps user address to the permissions bitmask (role), where each bit
* represents a permission
* @dev Bitmask 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
* represents all possible permissions
* @dev 'This' address mapping represents global features of the smart contract
*/
mapping(address => uint256) public userRoles;
/**
* @dev Fired in updateRole() and updateFeatures()
*
* @param _by operator which called the function
* @param _to address which was granted/revoked permissions
* @param _requested permissions requested
* @param _actual permissions effectively set
*/
event RoleUpdated(address indexed _by, address indexed _to, uint256 _requested, uint256 _actual);
/**
* @notice Creates an access control instance,
* setting contract creator to have full privileges
*/
constructor() {
// contract creator has full privileges
userRoles[msg.sender] = FULL_PRIVILEGES_MASK;
}
/**
* @notice Retrieves globally set of features enabled
*
* @dev Effectively reads userRoles role for the contract itself
*
* @return 256-bit bitmask of the features enabled
*/
function features() public view returns(uint256) {
// features are stored in 'this' address mapping of `userRoles` structure
return userRoles[address(this)];
}
/**
* @notice Updates set of the globally enabled features (`features`),
* taking into account sender's permissions
*
* @dev Requires transaction sender to have `ROLE_ACCESS_MANAGER` permission
* @dev Function is left for backward compatibility with older versions
*
* @param _mask bitmask representing a set of features to enable/disable
*/
function updateFeatures(uint256 _mask) public {
// delegate call to `updateRole`
updateRole(address(this), _mask);
}
/**
* @notice Updates set of permissions (role) for a given user,
* taking into account sender's permissions.
*
* @dev Setting role to zero is equivalent to removing an all permissions
* @dev Setting role to `FULL_PRIVILEGES_MASK` is equivalent to
* copying senders' permissions (role) to the user
* @dev Requires transaction sender to have `ROLE_ACCESS_MANAGER` permission
*
* @param operator address of a user to alter permissions for or zero
* to alter global features of the smart contract
* @param role bitmask representing a set of permissions to
* enable/disable for a user specified
*/
function updateRole(address operator, uint256 role) public {
// caller must have a permission to update user roles
require(isSenderInRole(ROLE_ACCESS_MANAGER), "access denied");
// evaluate the role and reassign it
userRoles[operator] = evaluateBy(msg.sender, userRoles[operator], role);
// fire an event
emit RoleUpdated(msg.sender, operator, role, userRoles[operator]);
}
/**
* @notice Determines the permission bitmask an operator can set on the
* target permission set
* @notice Used to calculate the permission bitmask to be set when requested
* in `updateRole` and `updateFeatures` functions
*
* @dev Calculated based on:
* 1) operator's own permission set read from userRoles[operator]
* 2) target permission set - what is already set on the target
* 3) desired permission set - what do we want set target to
*
* @dev Corner cases:
* 1) Operator is super admin and its permission set is `FULL_PRIVILEGES_MASK`:
* `desired` bitset is returned regardless of the `target` permission set value
* (what operator sets is what they get)
* 2) Operator with no permissions (zero bitset):
* `target` bitset is returned regardless of the `desired` value
* (operator has no authority and cannot modify anything)
*
* @dev Example:
* Consider an operator with the permissions bitmask 00001111
* is about to modify the target permission set 01010101
* Operator wants to set that permission set to 00110011
* Based on their role, an operator has the permissions
* to update only lowest 4 bits on the target, meaning that
* high 4 bits of the target set in this example is left
* unchanged and low 4 bits get changed as desired: 01010011
*
* @param operator address of the contract operator which is about to set the permissions
* @param target input set of permissions to operator is going to modify
* @param desired desired set of permissions operator would like to set
* @return resulting set of permissions given operator will set
*/
function evaluateBy(address operator, uint256 target, uint256 desired) public view returns(uint256) {
// read operator's permissions
uint256 p = userRoles[operator];
// taking into account operator's permissions,
// 1) enable the permissions desired on the `target`
target |= p & desired;
// 2) disable the permissions desired on the `target`
target &= FULL_PRIVILEGES_MASK ^ (p & (FULL_PRIVILEGES_MASK ^ desired));
// return calculated result
return target;
}
/**
* @notice Checks if requested set of features is enabled globally on the contract
*
* @param required set of features to check against
* @return true if all the features requested are enabled, false otherwise
*/
function isFeatureEnabled(uint256 required) public view returns(bool) {
// delegate call to `__hasRole`, passing `features` property
return __hasRole(features(), required);
}
/**
* @notice Checks if transaction sender `msg.sender` has all the permissions required
*
* @param required set of permissions (role) to check against
* @return true if all the permissions requested are enabled, false otherwise
*/
function isSenderInRole(uint256 required) public view returns(bool) {
// delegate call to `isOperatorInRole`, passing transaction sender
return isOperatorInRole(msg.sender, required);
}
/**
* @notice Checks if operator has all the permissions (role) required
*
* @param operator address of the user to check role for
* @param required set of permissions (role) to check
* @return true if all the permissions requested are enabled, false otherwise
*/
function isOperatorInRole(address operator, uint256 required) public view returns(bool) {
// delegate call to `__hasRole`, passing operator's permissions (role)
return __hasRole(userRoles[operator], required);
}
/**
* @dev Checks if role `actual` contains all the permissions required `required`
*
* @param actual existent role
* @param required required role
* @return true if actual has required role (all permissions), false otherwise
*/
function __hasRole(uint256 actual, uint256 required) internal pure returns(bool) {
// check the bitmask for the role required and return the result
return actual & required == required;
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_nft","type":"address"},{"internalType":"address","name":"_proxyRegistry","type":"address"},{"internalType":"uint32[]","name":"_rangeBounds","type":"uint32[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":false,"internalType":"string","name":"_oldVal","type":"string"},{"indexed":false,"internalType":"string","name":"_newVal","type":"string"}],"name":"BaseURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":false,"internalType":"uint256","name":"_optionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_to","type":"address"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_requested","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_actual","type":"uint256"}],"name":"RoleUpdated","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":"ROLE_ACCESS_MANAGER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_MINTER","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_OS_MANAGER","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_URI_MANAGER","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_optionId","type":"uint256"}],"name":"canMint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"currentTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"target","type":"uint256"},{"internalType":"uint256","name":"desired","type":"uint256"}],"name":"evaluateBy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"features","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"fireTransferEvents","outputs":[],"stateMutability":"nonpayable","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":"required","type":"uint256"}],"name":"isFeatureEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"isOperatorInRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"required","type":"uint256"}],"name":"isSenderInRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_optionId","type":"uint256"},{"internalType":"address","name":"_toAddress","type":"address"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numOptions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxyRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supportsFactoryInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenIdUpperBound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_optionId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"_mask","type":"uint256"}],"name":"updateFeatures","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"role","type":"uint256"}],"name":"updateRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRoles","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60e06040819052600060c08190526200001b9160029162000738565b503480156200002957600080fd5b5060405162001f3b38038062001f3b8339810160408190526200004c9162000810565b33600090815260208190526040902060001990556001600160a01b038316620000bc5760405162461bcd60e51b815260206004820152601760248201527f4e465420636f6e7472616374206973206e6f742073657400000000000000000060448201526064015b60405180910390fd5b6001600160a01b0382166200011e5760405162461bcd60e51b815260206004820152602160248201527f4f70656e5365612070726f7879207265676973747279206973206e6f742073656044820152601d60fa1b6064820152608401620000b3565b6001815111620001715760405162461bcd60e51b815260206004820152601960248201527f696e76616c6964206e756d626572206f66206f7074696f6e73000000000000006044820152606401620000b3565b606481600081518110620001895762000189620009db565b602002602001015163ffffffff1611620001f25760405162461bcd60e51b815260206004820152602360248201527f696e76616c69642072616e676520626f756e6420696e697469616c20656c656d604482015262195b9d60ea1b6064820152608401620000b3565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526001600160a01b038416906301ffc9a79060240160206040518083038186803b1580156200023957600080fd5b505afa1580156200024e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000274919062000911565b620002b85760405162461bcd60e51b8152602060048201526013602482015272756e6578706563746564204e4654207479706560681b6044820152606401620000b3565b6040516301ffc9a760e01b8152635b5e139f60e01b60048201526001600160a01b038416906301ffc9a79060240160206040518083038186803b158015620002ff57600080fd5b505afa15801562000314573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200033a919062000911565b6200037e5760405162461bcd60e51b8152602060048201526013602482015272756e6578706563746564204e4654207479706560681b6044820152606401620000b3565b6040516301ffc9a760e01b8152633197b5d160e21b60048201526001600160a01b038416906301ffc9a79060240160206040518083038186803b158015620003c557600080fd5b505afa158015620003da573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000400919062000911565b620004445760405162461bcd60e51b8152602060048201526013602482015272756e6578706563746564204e4654207479706560681b6044820152606401620000b3565b60005b6001825162000457919062000950565b8110156200051557816200046d82600162000935565b81518110620004805762000480620009db565b602002602001015163ffffffff16828281518110620004a357620004a3620009db565b602002602001015163ffffffff1610620005005760405162461bcd60e51b815260206004820152601460248201527f696e76616c69642072616e676520626f756e64730000000000000000000000006044820152606401620000b3565b806200050c81620009a7565b91505062000447565b506001600160601b0319606084811b8216608052600180546001600160a01b031916331781559084901b90911660a052815162000553919062000950565b600160146101000a81548163ffffffff021916908363ffffffff16021790555060005b6001825162000586919062000950565b8110156200062657818181518110620005a357620005a3620009db565b602002602001015163ffffffff16600360008381526020019081526020016000208190555081816001620005d8919062000935565b81518110620005eb57620005eb620009db565b602002602001015163ffffffff16600460008381526020019081526020016000208190555080806200061d90620009a7565b91505062000576565b50620006346000336200063d565b50505062000a07565b6200064b62400000620006ff565b620006895760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401620000b3565b60005b600154600160a01b900463ffffffff16811015620006fa5780826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a480620006f181620009a7565b9150506200068c565b505050565b60006200070d338362000713565b92915050565b6001600160a01b038216600090815260208190526040812054821682145b9392505050565b82805462000746906200096a565b90600052602060002090601f0160209004810192826200076a5760008555620007b5565b82601f106200078557805160ff1916838001178555620007b5565b82800160010185558215620007b5579182015b82811115620007b557825182559160200191906001019062000798565b50620007c3929150620007c7565b5090565b5b80821115620007c35760008155600101620007c8565b80516001600160a01b0381168114620007f657600080fd5b919050565b805163ffffffff81168114620007f657600080fd5b6000806000606084860312156200082657600080fd5b6200083184620007de565b9250602062000842818601620007de565b60408601519093506001600160401b03808211156200086057600080fd5b818701915087601f8301126200087557600080fd5b8151818111156200088a576200088a620009f1565b8060051b604051601f19603f83011681018181108582111715620008b257620008b2620009f1565b604052828152858101935084860182860187018c1015620008d257600080fd5b600095505b838610156200090057620008eb81620007fb565b855260019590950194938601938601620008d7565b508096505050505050509250925092565b6000602082840312156200092457600080fd5b815180151581146200073157600080fd5b600082198211156200094b576200094b620009c5565b500190565b600082821015620009655762000965620009c5565b500390565b600181811c908216806200097f57607f821691505b60208210811415620009a157634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415620009be57620009be620009c5565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60805160601c60a05160601c6114e562000a56600039600081816103a1015281816106f80152610b4b015260008181610420015281816104bb0152818161081201526108ed01526114e56000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c806395d89b411161010f578063c688d693116100a2578063e985e9c511610071578063e985e9c514610455578063ee5e17e914610468578063f822d5aa1461047b578063fcc2c0781461048e57600080fd5b8063c688d693146103f5578063c87b56dd14610408578063d56d229d1461041b578063d5bb7f671461044257600080fd5b8063b50cbd9f116100de578063b50cbd9f1461039c578063b712b808146103c3578063b7cbaf90146103cd578063c311c523146103ed57600080fd5b806395d89b4114610356578063ae5b102e1461035e578063ae682e2e14610371578063b48fa4971461037c57600080fd5b80635dd871a31161018757806374d5e1001161015657806374d5e100146103065780638da5cb5b1461032657806392afc33a1461033957806394bf804d1461034357600080fd5b80635dd871a3146102a25780636352211e146102b55780636c0360eb146102eb578063725f3626146102f357600080fd5b806323b872dd116101c357806323b872dd146102465780632b5214161461025b5780634b97aed91461027a57806355f804b31461028f57600080fd5b806301ffc9a7146101ea57806306fdde031461021257806314b7b4e114610227575b600080fd5b6101fd6101f8366004611044565b6104a1565b60405190151581526020015b60405180910390f35b61021a6104b7565b6040516102099190611212565b6102316210000081565b60405163ffffffff9091168152602001610209565b610259610254366004610fa2565b610553565b005b306000908152602081905260409020545b604051908152602001610209565b600154600160a01b900463ffffffff1661026c565b61025961029d36600461108b565b610562565b6101fd6102b0366004611179565b6105ee565b6102d36102c3366004611179565b506001546001600160a01b031690565b6040516001600160a01b039091168152602001610209565b61021a61062d565b6101fd610301366004611179565b6106bb565b61026c610314366004610f4c565b60006020819052908152604090205481565b6001546102d3906001600160a01b031681565b6102316201000081565b610259610351366004611192565b6106d4565b61021a6108e9565b61025961036c366004610fe3565b610944565b61026c600160ff1b81565b61026c61038a366004611179565b60036020526000908152604090205481565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6102316240000081565b61026c6103db366004611179565b60046020526000908152604090205481565b6101fd6109ee565b6101fd610403366004610fe3565b610a00565b61021a610416366004611179565b610a25565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b610259610450366004611179565b610ac5565b6101fd610463366004610f69565b610ad2565b610259610476366004610f69565b610bd8565b61026c61048936600461100f565b610c6d565b6101fd61049c366004611179565b610c98565b6001600160e01b031916631abf898b60e01b1490565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b15801561051257600080fd5b505afa158015610526573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261054e919081019061110b565b905090565b61055d81836106d4565b505050565b61056e62100000610c98565b6105935760405162461bcd60e51b815260040161058a906112d8565b60405180910390fd5b336001600160a01b03167fac455070f26733cc10c09e4389a74bf73bdb676d730ee31215c31d20daa880056002836040516105cf929190611225565b60405180910390a280516105ea906002906020840190610eb3565b5050565b600154600090600160a01b900463ffffffff16821080156106275750600082815260046020908152604080832054600390925290912054105b92915050565b6002805461063a906113d8565b80601f0160208091040260200160405190810160405280929190818152602001828054610666906113d8565b80156106b35780601f10610688576101008083540402835291602001916106b3565b820191906000526020600020905b81548152906001019060200180831161069657829003601f168201915b505050505081565b3060009081526020819052604081205482168214610627565b60015460405163c455279160e01b81526001600160a01b03918216600482015233917f0000000000000000000000000000000000000000000000000000000000000000169063c45527919060240160206040518083038186803b15801561073a57600080fd5b505afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610772919061106e565b6001600160a01b0316146107985760405162461bcd60e51b815260040161058a906112d8565b6107a1826105ee565b6107db5760405162461bcd60e51b815260206004820152600b60248201526a18d85b9b9bdd081b5a5b9d60aa1b604482015260640161058a565b600082815260036020526040908190205490516340c10f1960e01b81526001600160a01b03838116600483015260248201929092527f0000000000000000000000000000000000000000000000000000000000000000909116906340c10f1990604401600060405180830381600087803b15801561085857600080fd5b505af115801561086c573d6000803e3d6000fd5b505050600083815260036020526040908190205490516001600160a01b038416925033917ffd1ba5519feb014ad2f631cbd516bd3cec96be935749391554d122972593e7bf916108be91815260200190565b60405180910390a360008281526003602052604081208054916108e083611413565b91905055505050565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801561051257600080fd5b610951600160ff1b610c98565b61096d5760405162461bcd60e51b815260040161058a906112d8565b6001600160a01b03821660009081526020819052604090205461099290339083610c6d565b6001600160a01b03831660008181526020818152604091829020849055815185815290810193909352909133917f5a10526456f5116c0b7b80582c217d666243fd51b6a2d92c8011e601c2462e5f910160405180910390a35050565b600061054e631abf898b60e01b6104a1565b6001600160a01b038216600090815260208190526040812054821682145b9392505050565b606061062760028054610a37906113d8565b80601f0160208091040260200160405190810160405280929190818152602001828054610a63906113d8565b8015610ab05780601f10610a8557610100808354040283529160200191610ab0565b820191906000526020600020905b815481529060010190602001808311610a9357829003601f168201915b5050505050610ac084600a610ca4565b610e87565b610acf3082610944565b50565b6001546000906001600160a01b038481169116148015610b035750816001600160a01b0316836001600160a01b0316145b15610b1057506001610627565b6001546001600160a01b038481169116148015610a1e575060405163c455279160e01b81526001600160a01b038481166004830152808416917f00000000000000000000000000000000000000000000000000000000000000009091169063c45527919060240160206040518083038186803b158015610b8f57600080fd5b505afa158015610ba3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc7919061106e565b6001600160a01b0316149392505050565b610be462400000610c98565b610c005760405162461bcd60e51b815260040161058a906112d8565b60005b600154600160a01b900463ffffffff1681101561055d5780826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a480610c6581611413565b915050610c03565b6001600160a01b03929092166000908152602081905260409020546000198084188216189216171690565b60006106273383610a00565b60608160ff1660021480610cbb57508160ff166008145b80610cc957508160ff16600a145b80610cd757508160ff166010145b610ce057600080fd5b82610d0357506040805180820190915260018152600360fc1b6020820152610627565b60408051610100808252610120820190925260009160208201818036833701905050905060005b8415610db8576000610d3f60ff86168761142e565b90506000610d4e826030611358565b9050600a8260ff1610610d6957610d66600782611358565b90505b8060f81b848480610d7990611413565b955081518110610d8b57610d8b61146e565b60200101906001600160f81b031916908160001a905350610daf60ff87168861137d565b96505050610d2a565b60008167ffffffffffffffff811115610dd357610dd3611484565b6040519080825280601f01601f191660200182016040528015610dfd576020820181803683370190505b509050600091505b8051821015610e7e57828281518110610e2057610e2061146e565b602001015160f81c60f81b816001848451610e3b9190611391565b610e459190611391565b81518110610e5557610e5561146e565b60200101906001600160f81b031916908160001a90535081610e7681611413565b925050610e05565b95945050505050565b60608282604051602001610e9c9291906111e3565b604051602081830303815290604052905092915050565b828054610ebf906113d8565b90600052602060002090601f016020900481019282610ee15760008555610f27565b82601f10610efa57805160ff1916838001178555610f27565b82800160010185558215610f27579182015b82811115610f27578251825591602001919060010190610f0c565b50610f33929150610f37565b5090565b5b80821115610f335760008155600101610f38565b600060208284031215610f5e57600080fd5b8135610a1e8161149a565b60008060408385031215610f7c57600080fd5b8235610f878161149a565b91506020830135610f978161149a565b809150509250929050565b600080600060608486031215610fb757600080fd5b8335610fc28161149a565b92506020840135610fd28161149a565b929592945050506040919091013590565b60008060408385031215610ff657600080fd5b82356110018161149a565b946020939093013593505050565b60008060006060848603121561102457600080fd5b833561102f8161149a565b95602085013595506040909401359392505050565b60006020828403121561105657600080fd5b81356001600160e01b031981168114610a1e57600080fd5b60006020828403121561108057600080fd5b8151610a1e8161149a565b60006020828403121561109d57600080fd5b813567ffffffffffffffff8111156110b457600080fd5b8201601f810184136110c557600080fd5b80356110d86110d382611330565b6112ff565b8181528560208385010111156110ed57600080fd5b81602084016020830137600091810160200191909152949350505050565b60006020828403121561111d57600080fd5b815167ffffffffffffffff81111561113457600080fd5b8201601f8101841361114557600080fd5b80516111536110d382611330565b81815285602083850101111561116857600080fd5b610e7e8260208301602086016113a8565b60006020828403121561118b57600080fd5b5035919050565b600080604083850312156111a557600080fd5b823591506020830135610f978161149a565b600081518084526111cf8160208601602086016113a8565b601f01601f19169290920160200192915050565b600083516111f58184602088016113a8565b8351908301906112098183602088016113a8565b01949350505050565b602081526000610a1e60208301846111b7565b60408152600080845481600182811c91508083168061124557607f831692505b602080841082141561126557634e487b7160e01b86526022600452602486fd5b60408801849052606088018280156112845760018114611295576112c0565b60ff198716825282820197506112c0565b60008c81526020902060005b878110156112ba578154848201529086019084016112a1565b83019850505b5050878603818901525050505050610e7e81856111b7565b6020808252600d908201526c1858d8d95cdcc819195b9a5959609a1b604082015260600190565b604051601f8201601f1916810167ffffffffffffffff8111828210171561132857611328611484565b604052919050565b600067ffffffffffffffff82111561134a5761134a611484565b50601f01601f191660200190565b600060ff821660ff84168060ff0382111561137557611375611442565b019392505050565b60008261138c5761138c611458565b500490565b6000828210156113a3576113a3611442565b500390565b60005b838110156113c35781810151838201526020016113ab565b838111156113d2576000848401525b50505050565b600181811c908216806113ec57607f821691505b6020821081141561140d57634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561142757611427611442565b5060010190565b60008261143d5761143d611458565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610acf57600080fdfea26469706673582212207e1497318604667fc39804c4db68614256669c6fdd0f65cf49bf14e31cd321ea64736f6c63430008070033000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000001fad00000000000000000000000000000000000000000000000000000000000022cd000000000000000000000000000000000000000000000000000000000000231d
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101e55760003560e01c806395d89b411161010f578063c688d693116100a2578063e985e9c511610071578063e985e9c514610455578063ee5e17e914610468578063f822d5aa1461047b578063fcc2c0781461048e57600080fd5b8063c688d693146103f5578063c87b56dd14610408578063d56d229d1461041b578063d5bb7f671461044257600080fd5b8063b50cbd9f116100de578063b50cbd9f1461039c578063b712b808146103c3578063b7cbaf90146103cd578063c311c523146103ed57600080fd5b806395d89b4114610356578063ae5b102e1461035e578063ae682e2e14610371578063b48fa4971461037c57600080fd5b80635dd871a31161018757806374d5e1001161015657806374d5e100146103065780638da5cb5b1461032657806392afc33a1461033957806394bf804d1461034357600080fd5b80635dd871a3146102a25780636352211e146102b55780636c0360eb146102eb578063725f3626146102f357600080fd5b806323b872dd116101c357806323b872dd146102465780632b5214161461025b5780634b97aed91461027a57806355f804b31461028f57600080fd5b806301ffc9a7146101ea57806306fdde031461021257806314b7b4e114610227575b600080fd5b6101fd6101f8366004611044565b6104a1565b60405190151581526020015b60405180910390f35b61021a6104b7565b6040516102099190611212565b6102316210000081565b60405163ffffffff9091168152602001610209565b610259610254366004610fa2565b610553565b005b306000908152602081905260409020545b604051908152602001610209565b600154600160a01b900463ffffffff1661026c565b61025961029d36600461108b565b610562565b6101fd6102b0366004611179565b6105ee565b6102d36102c3366004611179565b506001546001600160a01b031690565b6040516001600160a01b039091168152602001610209565b61021a61062d565b6101fd610301366004611179565b6106bb565b61026c610314366004610f4c565b60006020819052908152604090205481565b6001546102d3906001600160a01b031681565b6102316201000081565b610259610351366004611192565b6106d4565b61021a6108e9565b61025961036c366004610fe3565b610944565b61026c600160ff1b81565b61026c61038a366004611179565b60036020526000908152604090205481565b6102d37f000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c181565b6102316240000081565b61026c6103db366004611179565b60046020526000908152604090205481565b6101fd6109ee565b6101fd610403366004610fe3565b610a00565b61021a610416366004611179565b610a25565b6102d37f000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c81565b610259610450366004611179565b610ac5565b6101fd610463366004610f69565b610ad2565b610259610476366004610f69565b610bd8565b61026c61048936600461100f565b610c6d565b6101fd61049c366004611179565b610c98565b6001600160e01b031916631abf898b60e01b1490565b60607f000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c6001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b15801561051257600080fd5b505afa158015610526573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261054e919081019061110b565b905090565b61055d81836106d4565b505050565b61056e62100000610c98565b6105935760405162461bcd60e51b815260040161058a906112d8565b60405180910390fd5b336001600160a01b03167fac455070f26733cc10c09e4389a74bf73bdb676d730ee31215c31d20daa880056002836040516105cf929190611225565b60405180910390a280516105ea906002906020840190610eb3565b5050565b600154600090600160a01b900463ffffffff16821080156106275750600082815260046020908152604080832054600390925290912054105b92915050565b6002805461063a906113d8565b80601f0160208091040260200160405190810160405280929190818152602001828054610666906113d8565b80156106b35780601f10610688576101008083540402835291602001916106b3565b820191906000526020600020905b81548152906001019060200180831161069657829003601f168201915b505050505081565b3060009081526020819052604081205482168214610627565b60015460405163c455279160e01b81526001600160a01b03918216600482015233917f000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1169063c45527919060240160206040518083038186803b15801561073a57600080fd5b505afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610772919061106e565b6001600160a01b0316146107985760405162461bcd60e51b815260040161058a906112d8565b6107a1826105ee565b6107db5760405162461bcd60e51b815260206004820152600b60248201526a18d85b9b9bdd081b5a5b9d60aa1b604482015260640161058a565b600082815260036020526040908190205490516340c10f1960e01b81526001600160a01b03838116600483015260248201929092527f000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c909116906340c10f1990604401600060405180830381600087803b15801561085857600080fd5b505af115801561086c573d6000803e3d6000fd5b505050600083815260036020526040908190205490516001600160a01b038416925033917ffd1ba5519feb014ad2f631cbd516bd3cec96be935749391554d122972593e7bf916108be91815260200190565b60405180910390a360008281526003602052604081208054916108e083611413565b91905055505050565b60607f000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c6001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801561051257600080fd5b610951600160ff1b610c98565b61096d5760405162461bcd60e51b815260040161058a906112d8565b6001600160a01b03821660009081526020819052604090205461099290339083610c6d565b6001600160a01b03831660008181526020818152604091829020849055815185815290810193909352909133917f5a10526456f5116c0b7b80582c217d666243fd51b6a2d92c8011e601c2462e5f910160405180910390a35050565b600061054e631abf898b60e01b6104a1565b6001600160a01b038216600090815260208190526040812054821682145b9392505050565b606061062760028054610a37906113d8565b80601f0160208091040260200160405190810160405280929190818152602001828054610a63906113d8565b8015610ab05780601f10610a8557610100808354040283529160200191610ab0565b820191906000526020600020905b815481529060010190602001808311610a9357829003601f168201915b5050505050610ac084600a610ca4565b610e87565b610acf3082610944565b50565b6001546000906001600160a01b038481169116148015610b035750816001600160a01b0316836001600160a01b0316145b15610b1057506001610627565b6001546001600160a01b038481169116148015610a1e575060405163c455279160e01b81526001600160a01b038481166004830152808416917f000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c19091169063c45527919060240160206040518083038186803b158015610b8f57600080fd5b505afa158015610ba3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc7919061106e565b6001600160a01b0316149392505050565b610be462400000610c98565b610c005760405162461bcd60e51b815260040161058a906112d8565b60005b600154600160a01b900463ffffffff1681101561055d5780826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a480610c6581611413565b915050610c03565b6001600160a01b03929092166000908152602081905260409020546000198084188216189216171690565b60006106273383610a00565b60608160ff1660021480610cbb57508160ff166008145b80610cc957508160ff16600a145b80610cd757508160ff166010145b610ce057600080fd5b82610d0357506040805180820190915260018152600360fc1b6020820152610627565b60408051610100808252610120820190925260009160208201818036833701905050905060005b8415610db8576000610d3f60ff86168761142e565b90506000610d4e826030611358565b9050600a8260ff1610610d6957610d66600782611358565b90505b8060f81b848480610d7990611413565b955081518110610d8b57610d8b61146e565b60200101906001600160f81b031916908160001a905350610daf60ff87168861137d565b96505050610d2a565b60008167ffffffffffffffff811115610dd357610dd3611484565b6040519080825280601f01601f191660200182016040528015610dfd576020820181803683370190505b509050600091505b8051821015610e7e57828281518110610e2057610e2061146e565b602001015160f81c60f81b816001848451610e3b9190611391565b610e459190611391565b81518110610e5557610e5561146e565b60200101906001600160f81b031916908160001a90535081610e7681611413565b925050610e05565b95945050505050565b60608282604051602001610e9c9291906111e3565b604051602081830303815290604052905092915050565b828054610ebf906113d8565b90600052602060002090601f016020900481019282610ee15760008555610f27565b82601f10610efa57805160ff1916838001178555610f27565b82800160010185558215610f27579182015b82811115610f27578251825591602001919060010190610f0c565b50610f33929150610f37565b5090565b5b80821115610f335760008155600101610f38565b600060208284031215610f5e57600080fd5b8135610a1e8161149a565b60008060408385031215610f7c57600080fd5b8235610f878161149a565b91506020830135610f978161149a565b809150509250929050565b600080600060608486031215610fb757600080fd5b8335610fc28161149a565b92506020840135610fd28161149a565b929592945050506040919091013590565b60008060408385031215610ff657600080fd5b82356110018161149a565b946020939093013593505050565b60008060006060848603121561102457600080fd5b833561102f8161149a565b95602085013595506040909401359392505050565b60006020828403121561105657600080fd5b81356001600160e01b031981168114610a1e57600080fd5b60006020828403121561108057600080fd5b8151610a1e8161149a565b60006020828403121561109d57600080fd5b813567ffffffffffffffff8111156110b457600080fd5b8201601f810184136110c557600080fd5b80356110d86110d382611330565b6112ff565b8181528560208385010111156110ed57600080fd5b81602084016020830137600091810160200191909152949350505050565b60006020828403121561111d57600080fd5b815167ffffffffffffffff81111561113457600080fd5b8201601f8101841361114557600080fd5b80516111536110d382611330565b81815285602083850101111561116857600080fd5b610e7e8260208301602086016113a8565b60006020828403121561118b57600080fd5b5035919050565b600080604083850312156111a557600080fd5b823591506020830135610f978161149a565b600081518084526111cf8160208601602086016113a8565b601f01601f19169290920160200192915050565b600083516111f58184602088016113a8565b8351908301906112098183602088016113a8565b01949350505050565b602081526000610a1e60208301846111b7565b60408152600080845481600182811c91508083168061124557607f831692505b602080841082141561126557634e487b7160e01b86526022600452602486fd5b60408801849052606088018280156112845760018114611295576112c0565b60ff198716825282820197506112c0565b60008c81526020902060005b878110156112ba578154848201529086019084016112a1565b83019850505b5050878603818901525050505050610e7e81856111b7565b6020808252600d908201526c1858d8d95cdcc819195b9a5959609a1b604082015260600190565b604051601f8201601f1916810167ffffffffffffffff8111828210171561132857611328611484565b604052919050565b600067ffffffffffffffff82111561134a5761134a611484565b50601f01601f191660200190565b600060ff821660ff84168060ff0382111561137557611375611442565b019392505050565b60008261138c5761138c611458565b500490565b6000828210156113a3576113a3611442565b500390565b60005b838110156113c35781810151838201526020016113ab565b838111156113d2576000848401525b50505050565b600181811c908216806113ec57607f821691505b6020821081141561140d57634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561142757611427611442565b5060010190565b60008261143d5761143d611458565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610acf57600080fdfea26469706673582212207e1497318604667fc39804c4db68614256669c6fdd0f65cf49bf14e31cd321ea64736f6c63430008070033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000001fad00000000000000000000000000000000000000000000000000000000000022cd000000000000000000000000000000000000000000000000000000000000231d
-----Decoded View---------------
Arg [0] : _nft (address): 0xDd70AF84BA86F29bf437756B655110D134b5651C
Arg [1] : _proxyRegistry (address): 0xa5409ec958C83C3f309868babACA7c86DCB077c1
Arg [2] : _rangeBounds (uint32[]): 101,8109,8909,8989
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c
Arg [1] : 000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000065
Arg [5] : 0000000000000000000000000000000000000000000000000000000000001fad
Arg [6] : 00000000000000000000000000000000000000000000000000000000000022cd
Arg [7] : 000000000000000000000000000000000000000000000000000000000000231d
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.
Add Token to MetaMask (Web3)