Source Code
Latest 25 from a total of 25 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Create Series | 38301422 | 10 hrs ago | IN | 0 ETH | 0.00002621 | ||||
| Set Token URI | 38227032 | 2 days ago | IN | 0 ETH | 0.00000029 | ||||
| Set Token URI | 38226682 | 2 days ago | IN | 0 ETH | 0.00000043 | ||||
| Set Token URI | 38226609 | 2 days ago | IN | 0 ETH | 0.00000051 | ||||
| Create Series | 38191388 | 2 days ago | IN | 0 ETH | 0.00000202 | ||||
| Create Series | 38190470 | 3 days ago | IN | 0 ETH | 0.00000228 | ||||
| Create Series | 38190071 | 3 days ago | IN | 0 ETH | 0.0000032 | ||||
| Create Series | 38189520 | 3 days ago | IN | 0 ETH | 0.00000275 | ||||
| Set Token URI | 38150103 | 3 days ago | IN | 0 ETH | 0.00000018 | ||||
| Create Series | 38149771 | 3 days ago | IN | 0 ETH | 0.00000824 | ||||
| Create Series | 38145884 | 4 days ago | IN | 0 ETH | 0.00001485 | ||||
| Create Series | 38132765 | 4 days ago | IN | 0 ETH | 0.00001124 | ||||
| Set Token URI | 38122570 | 4 days ago | IN | 0 ETH | 0.0000002 | ||||
| Create Series | 38122513 | 4 days ago | IN | 0 ETH | 0.00000207 | ||||
| Create Series | 38092827 | 5 days ago | IN | 0 ETH | 0.00001652 | ||||
| Create Series | 38080011 | 5 days ago | IN | 0 ETH | 0.000103 | ||||
| Create Series | 38021117 | 6 days ago | IN | 0 ETH | 0.00000106 | ||||
| Create Series | 38008578 | 7 days ago | IN | 0 ETH | 0.00000069 | ||||
| Create Series | 37954908 | 8 days ago | IN | 0 ETH | 0.0000057 | ||||
| Create Series | 37954705 | 8 days ago | IN | 0 ETH | 0.0000079 | ||||
| Create Series | 37953491 | 8 days ago | IN | 0 ETH | 0.00000518 | ||||
| Create Series | 37935229 | 8 days ago | IN | 0 ETH | 0.00000072 | ||||
| Create Series | 37934365 | 8 days ago | IN | 0 ETH | 0.00000198 | ||||
| Create Series | 37918804 | 9 days ago | IN | 0 ETH | 0.00000159 | ||||
| Create Series | 37914113 | 9 days ago | IN | 0 ETH | 0.00000839 |
Latest 1 internal transaction
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 14115667 | 560 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ManifoldERC721Edition
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@manifoldxyz/libraries-solidity/contracts/access/IAdminControl.sol";
import "@manifoldxyz/creator-core-solidity/contracts/core/IERC721CreatorCore.sol";
import "@manifoldxyz/creator-core-solidity/contracts/extensions/CreatorExtension.sol";
import "@manifoldxyz/creator-core-solidity/contracts/extensions/ICreatorExtensionTokenURI.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "../libraries/IERC721CreatorCoreVersion.sol";
import "./IManifoldERC721Edition.sol";
/**
* Manifold ERC721 Edition Controller Implementation
*/
contract ManifoldERC721Edition is CreatorExtension, ICreatorExtensionTokenURI, IManifoldERC721Edition, ReentrancyGuard {
using Strings for uint256;
struct IndexRange {
uint256 startIndex;
uint256 count;
}
string private constant ARWEAVE_PREFIX = "https://arweave.net/";
string private constant IPFS_PREFIX = "ipfs://";
uint256 private constant MAX_UINT_24 = 0xffffff;
uint256 private constant MAX_UINT_56 = 0xffffffffffffff;
uint256 private constant MAX_UINT_192 = 0xffffffffffffffffffffffffffffffffffffffffffffffff;
mapping(address => mapping(uint256 => EditionInfo)) _editionInfo;
mapping(address => mapping(uint256 => IndexRange[])) _indexRanges;
mapping(address => uint256[]) _creatorInstanceIds;
/**
* @dev Only allows approved admins to call the specified function
*/
modifier creatorAdminRequired(address creator) {
if (!IAdminControl(creator).isAdmin(msg.sender)) revert("Must be owner or admin of creator contract");
_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override(CreatorExtension, IERC165) returns (bool) {
return
interfaceId == type(ICreatorExtensionTokenURI).interfaceId ||
interfaceId == type(IManifoldERC721Edition).interfaceId ||
CreatorExtension.supportsInterface(interfaceId);
}
/**
* @dev See {IManifoldERC721Edition-createSeries}.
*/
function createSeries(address creatorCore, uint256 instanceId, uint24 maxSupply_, StorageProtocol storageProtocol, string calldata location, Recipient[] memory recipients) external override creatorAdminRequired(creatorCore) {
if (instanceId == 0 ||
instanceId > MAX_UINT_56 ||
maxSupply_ == 0 ||
storageProtocol == StorageProtocol.INVALID ||
_editionInfo[creatorCore][instanceId].storageProtocol != StorageProtocol.INVALID
) revert InvalidInput();
uint8 creatorContractVersion;
try IERC721CreatorCoreVersion(creatorCore).VERSION() returns(uint256 version) {
require(version <= 255, "Unsupported contract version");
creatorContractVersion = uint8(version);
} catch {}
_editionInfo[creatorCore][instanceId] = EditionInfo({
maxSupply: maxSupply_,
totalSupply: 0,
contractVersion: creatorContractVersion,
storageProtocol: storageProtocol,
location: location,
firstTokenId: 0
});
if (creatorContractVersion < 3) {
_creatorInstanceIds[creatorCore].push(instanceId);
}
emit SeriesCreated(msg.sender, creatorCore, instanceId, maxSupply_);
if (recipients.length > 0) _mintTokens(creatorCore, instanceId, _editionInfo[creatorCore][instanceId], recipients);
}
/**
* See {IManifoldERC721Edition-setTokenURI}.
*/
function setTokenURI(address creatorCore, uint256 instanceId, StorageProtocol storageProtocol, string calldata location) external override creatorAdminRequired(creatorCore) {
if (storageProtocol == StorageProtocol.INVALID) revert InvalidInput();
EditionInfo storage info = _getEditionInfo(creatorCore, instanceId);
info.storageProtocol = storageProtocol;
info.location = location;
}
function _getEditionInfo(address creatorCore, uint256 instanceId) private view returns(EditionInfo storage info) {
info = _editionInfo[creatorCore][instanceId];
if (info.storageProtocol == StorageProtocol.INVALID) revert InvalidEdition();
}
/**
* @dev See {IManifoldERC721Edition-getEditionInfo}.
*
* This is the public version of the above internal function. Separate function because it returns EditionInfo
* memory instead of storage.
*/
function getEditionInfo(address creatorCore, uint256 instanceId) public view returns(EditionInfo memory info) {
info = _editionInfo[creatorCore][instanceId];
if (info.storageProtocol == StorageProtocol.INVALID) revert InvalidEdition();
}
/**
* @dev See {IManifoldERC721Edition-getInstanceIdsForTokens}.
*/
function getInstanceIdsForTokens(address creatorCore, uint256[] calldata tokenIds) external view override returns(uint256[] memory instanceIds) {
instanceIds = new uint256[](tokenIds.length);
for (uint256 i; i < tokenIds.length;) {
uint256 tokenId = tokenIds[i];
try IERC721CreatorCore(creatorCore).tokenExtension(tokenId) returns(address tokenExtension) {
if (tokenExtension == address(this)) {
uint256 creatorContractVersion;
uint256 instanceId;
try IERC721CreatorCoreVersion(creatorCore).VERSION() returns(uint256 version) {
creatorContractVersion = version;
} catch {}
if (creatorContractVersion >= 3) {
// Contract versions 3+ support storage of data with the token mint, so use that
uint80 tokenData = IERC721CreatorCore(creatorCore).tokenData(tokenId);
instanceId = uint56(tokenData >> 24);
} else {
(instanceId, ) = _tokenInstanceAndIndex(creatorCore, tokenId);
}
instanceIds[i] = instanceId;
}
} catch {}
unchecked{++i;}
}
}
/**
* @dev See {IManifoldERC721Edition-getInstanceTokenIds}.
*/
function getInstanceTokenIds(address creatorCore, uint256 instanceId) external view returns(uint256[] memory tokenIds) {
EditionInfo storage info = _getEditionInfo(creatorCore, instanceId);
uint256 creatorContractVersion;
tokenIds = new uint256[](info.totalSupply);
try IERC721CreatorCoreVersion(creatorCore).VERSION() returns(uint256 version) {
creatorContractVersion = version;
} catch {}
if (creatorContractVersion >= 3) {
// We do not have index ranges, so seek based on first tokenId
uint256 tokenId = info.firstTokenId;
uint256 foundTokens;
while (foundTokens < info.totalSupply) {
try IERC721CreatorCore(creatorCore).tokenExtension(tokenId) returns(address tokenExtension) {
if (tokenExtension == address(this)) {
uint80 tokenData = IERC721CreatorCore(creatorCore).tokenData(tokenId);
if (instanceId == uint56(tokenData >> 24)) {
tokenIds[foundTokens] = tokenId;
unchecked{++foundTokens;}
}
}
} catch {}
unchecked{++tokenId;}
}
} else {
// We have index ranges, so we can just iterate through them
IndexRange[] memory indexRanges = _indexRanges[creatorCore][instanceId];
uint256 current;
for (uint256 i; i < indexRanges.length;) {
IndexRange memory currentIndex = indexRanges[i];
for (uint256 j; j < currentIndex.count;) {
tokenIds[current] = currentIndex.startIndex + j;
unchecked{++current; ++j;}
}
unchecked{++i;}
}
}
}
/**
* @dev See {ICreatorExtensionTokenURI-tokenURI}.
*/
function tokenURI(address creatorCore, uint256 tokenId) external view override returns (string memory) {
uint256 creatorContractVersion;
try IERC721CreatorCoreVersion(creatorCore).VERSION() returns(uint256 version) {
creatorContractVersion = version;
} catch {}
uint256 instanceId;
uint256 index;
if (creatorContractVersion >= 3) {
// Contract versions 3+ support storage of data with the token mint, so use that
uint80 tokenData = IERC721CreatorCore(creatorCore).tokenData(tokenId);
instanceId = uint56(tokenData >> 24);
if (instanceId == 0) revert InvalidToken();
index = uint256(tokenData & MAX_UINT_24);
} else {
(instanceId, index) = _tokenInstanceAndIndex(creatorCore, tokenId);
}
EditionInfo storage info = _getEditionInfo(creatorCore, instanceId);
string memory prefix = "";
if (info.storageProtocol == StorageProtocol.ARWEAVE) {
prefix = ARWEAVE_PREFIX;
} else if (info.storageProtocol == StorageProtocol.IPFS) {
prefix = IPFS_PREFIX;
}
return string(abi.encodePacked(prefix, info.location, "/", (index+1).toString()));
}
/**
* @dev See {IManifoldERC721Edition-mint}.
*/
function mint(address creatorCore, uint256 instanceId, uint24 currentSupply, Recipient[] memory recipients) external override nonReentrant creatorAdminRequired(creatorCore) {
EditionInfo storage info = _getEditionInfo(creatorCore, instanceId);
if (currentSupply != info.totalSupply) revert InvalidInput();
_mintTokens(creatorCore, instanceId, info, recipients);
}
function _mintTokens(address creatorCore, uint256 instanceId, EditionInfo storage info, Recipient[] memory recipients) private {
if (recipients.length == 0) revert InvalidInput();
if (info.totalSupply+1 > info.maxSupply) revert TooManyRequested();
uint256[] memory tokenIdResults;
if (info.contractVersion >= 3) {
uint16 count = 0;
uint24 totalSupply_ = info.totalSupply;
uint24 maxSupply_ = info.maxSupply;
uint256 newMintIndex = totalSupply_;
// Contract versions 3+ support storage of data with the token mint, so use that
// to avoid additional storage costs
for (uint256 i; i < recipients.length;) {
uint16 mintCount = recipients[i].count;
if (mintCount == 0) revert InvalidInput();
count += mintCount;
if (totalSupply_+count > maxSupply_) revert TooManyRequested();
uint80[] memory tokenDatas = new uint80[](mintCount);
for (uint256 j; j < mintCount;) {
tokenDatas[j] = uint56(instanceId) << 24 | uint24(newMintIndex+j);
unchecked {++j;}
}
// Airdrop the tokens
tokenIdResults = IERC721CreatorCore(creatorCore).mintExtensionBatch(recipients[i].recipient, tokenDatas);
if (i == 0 && info.firstTokenId == 0) {
if (tokenIdResults[0] > MAX_UINT_192) revert InvalidInput();
info.firstTokenId = uint192(tokenIdResults[0]);
}
// Increment newMintIndex for the next airdrop
unchecked{newMintIndex += mintCount;}
unchecked{++i;}
}
info.totalSupply += count;
} else {
uint256 startIndex;
uint16 count = 0;
uint24 totalSupply_ = info.totalSupply;
uint24 maxSupply_ = info.maxSupply;
for (uint256 i; i < recipients.length;) {
if (recipients[i].count == 0) revert InvalidInput();
count += recipients[i].count;
if (totalSupply_+count > maxSupply_) revert TooManyRequested();
tokenIdResults = IERC721CreatorCore(creatorCore).mintExtensionBatch(recipients[i].recipient, recipients[i].count);
if (i == 0) {
startIndex = tokenIdResults[0];
if (info.firstTokenId == 0) {
if (startIndex > MAX_UINT_192) revert InvalidInput();
info.firstTokenId = uint192(startIndex);
}
}
unchecked{++i;}
}
_updateIndexRanges(creatorCore, instanceId, info, startIndex, count);
}
}
/**
* @dev Update the index ranges, which is used to figure out the index from a tokenId
*/
function _updateIndexRanges(address creatorCore, uint256 instanceId, EditionInfo storage info, uint256 startIndex, uint16 count) internal {
IndexRange[] storage indexRanges = _indexRanges[creatorCore][instanceId];
if (indexRanges.length == 0) {
indexRanges.push(IndexRange(startIndex, count));
} else {
IndexRange storage lastIndexRange = indexRanges[indexRanges.length-1];
if ((lastIndexRange.startIndex + lastIndexRange.count) == startIndex) {
lastIndexRange.count += count;
} else {
indexRanges.push(IndexRange(startIndex, count));
}
}
info.totalSupply += count;
}
/**
* @dev Index from tokenId
*/
function _tokenInstanceAndIndex(address creatorCore, uint256 tokenId) internal view returns(uint256, uint256) {
// Go through all their series until we find the tokenId
for (uint256 i; i < _creatorInstanceIds[creatorCore].length;) {
uint256 instanceId = _creatorInstanceIds[creatorCore][i];
IndexRange[] memory indexRanges = _indexRanges[creatorCore][instanceId];
uint256 offset;
for (uint j; j < indexRanges.length;) {
IndexRange memory currentIndex = indexRanges[j];
if (tokenId < currentIndex.startIndex) break;
if (tokenId >= currentIndex.startIndex && tokenId < currentIndex.startIndex + currentIndex.count) {
return (instanceId, tokenId - currentIndex.startIndex + offset);
}
offset += currentIndex.count;
unchecked{++j;}
}
unchecked{++i;}
}
revert InvalidToken();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @dev Interface for admin control
*/
interface IAdminControl is IERC165 {
event AdminApproved(address indexed account, address indexed sender);
event AdminRevoked(address indexed account, address indexed sender);
/**
* @dev gets address of all admins
*/
function getAdmins() external view returns (address[] memory);
/**
* @dev add an admin. Can only be called by contract owner.
*/
function approveAdmin(address admin) external;
/**
* @dev remove an admin. Can only be called by contract owner.
*/
function revokeAdmin(address admin) external;
/**
* @dev checks whether or not given address is an admin
* Returns True if they are
*/
function isAdmin(address admin) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "./ICreatorCore.sol";
/**
* @dev Core ERC721 creator interface
*/
interface IERC721CreatorCore is ICreatorCore {
/**
* @dev mint a token with no extension. Can only be called by an admin.
* Returns tokenId minted
*/
function mintBase(address to) external returns (uint256);
/**
* @dev mint a token with no extension. Can only be called by an admin.
* Returns tokenId minted
*/
function mintBase(address to, string calldata uri) external returns (uint256);
/**
* @dev batch mint a token with no extension. Can only be called by an admin.
* Returns tokenId minted
*/
function mintBaseBatch(address to, uint16 count) external returns (uint256[] memory);
/**
* @dev batch mint a token with no extension. Can only be called by an admin.
* Returns tokenId minted
*/
function mintBaseBatch(address to, string[] calldata uris) external returns (uint256[] memory);
/**
* @dev mint a token. Can only be called by a registered extension.
* Returns tokenId minted
*/
function mintExtension(address to) external returns (uint256);
/**
* @dev mint a token. Can only be called by a registered extension.
* Returns tokenId minted
*/
function mintExtension(address to, string calldata uri) external returns (uint256);
/**
* @dev mint a token. Can only be called by a registered extension.
* Returns tokenId minted
*/
function mintExtension(address to, uint80 data) external returns (uint256);
/**
* @dev batch mint a token. Can only be called by a registered extension.
* Returns tokenIds minted
*/
function mintExtensionBatch(address to, uint16 count) external returns (uint256[] memory);
/**
* @dev batch mint a token. Can only be called by a registered extension.
* Returns tokenId minted
*/
function mintExtensionBatch(address to, string[] calldata uris) external returns (uint256[] memory);
/**
* @dev batch mint a token. Can only be called by a registered extension.
* Returns tokenId minted
*/
function mintExtensionBatch(address to, uint80[] calldata data) external returns (uint256[] memory);
/**
* @dev burn a token. Can only be called by token owner or approved address.
* On burn, calls back to the registered extension's onBurn method
*/
function burn(uint256 tokenId) external;
/**
* @dev get token data
*/
function tokenData(uint256 tokenId) external view returns (uint80);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
/**
* @dev Base creator extension variables
*/
abstract contract CreatorExtension is ERC165 {
/**
* @dev Legacy extension interface identifiers
*
* {IERC165-supportsInterface} needs to return 'true' for this interface
* in order backwards compatible with older creator contracts
*/
bytes4 constant internal LEGACY_EXTENSION_INTERFACE = 0x7005caad;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165) returns (bool) {
return interfaceId == LEGACY_EXTENSION_INTERFACE
|| super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @dev Implement this if you want your extension to have overloadable URI's
*/
interface ICreatorExtensionTokenURI is IERC165 {
/**
* Get the uri for a given creator/tokenId
*/
function tokenURI(address creator, uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC721CreatorCoreVersion {
function VERSION() external view returns(uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
/**
* Manifold ERC721 Edition Controller interface
*/
interface IManifoldERC721Edition {
error InvalidEdition();
error InvalidInput();
error TooManyRequested();
error InvalidToken();
event SeriesCreated(address caller, address creatorCore, uint256 series, uint256 maxSupply);
struct Recipient {
address recipient;
uint16 count;
}
enum StorageProtocol { INVALID, NONE, ARWEAVE, IPFS }
struct EditionInfo {
uint192 firstTokenId;
uint8 contractVersion;
uint24 totalSupply;
uint24 maxSupply;
StorageProtocol storageProtocol;
string location;
}
/**
* @dev Create a new series. Returns the series id.
*/
function createSeries(address creatorCore, uint256 instanceId, uint24 maxSupply_, StorageProtocol storageProtocol, string calldata location, Recipient[] memory recipients) external;
/**
* @dev Set the token uri prefix
*/
function setTokenURI(address creatorCore, uint256 instanceId, StorageProtocol storageProtocol, string calldata location) external;
/**
* @dev Mint NFTs to a single recipient
*/
function mint(address creatorCore, uint256 instanceId, uint24 currentSupply, Recipient[] memory recipients) external;
/**
* @dev Get the EditionInfo for a Series
*/
function getEditionInfo(address creatorCore, uint256 instanceId) external view returns(EditionInfo memory);
/**
* @dev Get the instance ids for a set of token
*/
function getInstanceIdsForTokens(address creatorCore, uint256[] calldata tokenIds) external view returns(uint256[] memory);
/**
* @dev Get all the token ids for an instance
*/
function getInstanceTokenIds(address creatorCore, uint256 instanceId) external view returns(uint256[] memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @dev Core creator interface
*/
interface ICreatorCore is IERC165 {
event ExtensionRegistered(address indexed extension, address indexed sender);
event ExtensionUnregistered(address indexed extension, address indexed sender);
event ExtensionBlacklisted(address indexed extension, address indexed sender);
event MintPermissionsUpdated(address indexed extension, address indexed permissions, address indexed sender);
event RoyaltiesUpdated(uint256 indexed tokenId, address payable[] receivers, uint256[] basisPoints);
event DefaultRoyaltiesUpdated(address payable[] receivers, uint256[] basisPoints);
event ApproveTransferUpdated(address extension);
event ExtensionRoyaltiesUpdated(address indexed extension, address payable[] receivers, uint256[] basisPoints);
event ExtensionApproveTransferUpdated(address indexed extension, bool enabled);
/**
* @dev gets address of all extensions
*/
function getExtensions() external view returns (address[] memory);
/**
* @dev add an extension. Can only be called by contract owner or admin.
* extension address must point to a contract implementing ICreatorExtension.
* Returns True if newly added, False if already added.
*/
function registerExtension(address extension, string calldata baseURI) external;
/**
* @dev add an extension. Can only be called by contract owner or admin.
* extension address must point to a contract implementing ICreatorExtension.
* Returns True if newly added, False if already added.
*/
function registerExtension(address extension, string calldata baseURI, bool baseURIIdentical) external;
/**
* @dev add an extension. Can only be called by contract owner or admin.
* Returns True if removed, False if already removed.
*/
function unregisterExtension(address extension) external;
/**
* @dev blacklist an extension. Can only be called by contract owner or admin.
* This function will destroy all ability to reference the metadata of any tokens created
* by the specified extension. It will also unregister the extension if needed.
* Returns True if removed, False if already removed.
*/
function blacklistExtension(address extension) external;
/**
* @dev set the baseTokenURI of an extension. Can only be called by extension.
*/
function setBaseTokenURIExtension(string calldata uri) external;
/**
* @dev set the baseTokenURI of an extension. Can only be called by extension.
* For tokens with no uri configured, tokenURI will return "uri+tokenId"
*/
function setBaseTokenURIExtension(string calldata uri, bool identical) external;
/**
* @dev set the common prefix of an extension. Can only be called by extension.
* If configured, and a token has a uri set, tokenURI will return "prefixURI+tokenURI"
* Useful if you want to use ipfs/arweave
*/
function setTokenURIPrefixExtension(string calldata prefix) external;
/**
* @dev set the tokenURI of a token extension. Can only be called by extension that minted token.
*/
function setTokenURIExtension(uint256 tokenId, string calldata uri) external;
/**
* @dev set the tokenURI of a token extension for multiple tokens. Can only be called by extension that minted token.
*/
function setTokenURIExtension(uint256[] memory tokenId, string[] calldata uri) external;
/**
* @dev set the baseTokenURI for tokens with no extension. Can only be called by owner/admin.
* For tokens with no uri configured, tokenURI will return "uri+tokenId"
*/
function setBaseTokenURI(string calldata uri) external;
/**
* @dev set the common prefix for tokens with no extension. Can only be called by owner/admin.
* If configured, and a token has a uri set, tokenURI will return "prefixURI+tokenURI"
* Useful if you want to use ipfs/arweave
*/
function setTokenURIPrefix(string calldata prefix) external;
/**
* @dev set the tokenURI of a token with no extension. Can only be called by owner/admin.
*/
function setTokenURI(uint256 tokenId, string calldata uri) external;
/**
* @dev set the tokenURI of multiple tokens with no extension. Can only be called by owner/admin.
*/
function setTokenURI(uint256[] memory tokenIds, string[] calldata uris) external;
/**
* @dev set a permissions contract for an extension. Used to control minting.
*/
function setMintPermissions(address extension, address permissions) external;
/**
* @dev Configure so transfers of tokens created by the caller (must be extension) gets approval
* from the extension before transferring
*/
function setApproveTransferExtension(bool enabled) external;
/**
* @dev get the extension of a given token
*/
function tokenExtension(uint256 tokenId) external view returns (address);
/**
* @dev Set default royalties
*/
function setRoyalties(address payable[] calldata receivers, uint256[] calldata basisPoints) external;
/**
* @dev Set royalties of a token
*/
function setRoyalties(uint256 tokenId, address payable[] calldata receivers, uint256[] calldata basisPoints) external;
/**
* @dev Set royalties of an extension
*/
function setRoyaltiesExtension(address extension, address payable[] calldata receivers, uint256[] calldata basisPoints) external;
/**
* @dev Get royalites of a token. Returns list of receivers and basisPoints
*/
function getRoyalties(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory);
// Royalty support for various other standards
function getFeeRecipients(uint256 tokenId) external view returns (address payable[] memory);
function getFeeBps(uint256 tokenId) external view returns (uint[] memory);
function getFees(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory);
function royaltyInfo(uint256 tokenId, uint256 value) external view returns (address, uint256);
/**
* @dev Set the default approve transfer contract location.
*/
function setApproveTransfer(address extension) external;
/**
* @dev Get the default approve transfer contract location.
*/
function getApproveTransfer() external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}{
"remappings": [
"create2-scripts/=lib/create2-helpers/script/",
"create2-helpers/=lib/create2-helpers/src/",
"forge-std/=lib/forge-std/src/",
"@ensdomains/=node_modules/@ensdomains/",
"@manifoldxyz/=node_modules/@manifoldxyz/",
"@openzeppelin/=node_modules/@openzeppelin/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/operator-filter-registry/lib/openzeppelin-contracts/lib/erc4626-tests/",
"eth-gas-reporter/=node_modules/eth-gas-reporter/",
"hardhat/=node_modules/hardhat/",
"murky/=lib/murky/src/",
"openzeppelin-contracts-upgradeable/=lib/operator-filter-registry/lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/murky/lib/openzeppelin-contracts/",
"operator-filter-registry/=node_modules/operator-filter-registry/",
"truffle/=node_modules/truffle/"
],
"optimizer": {
"enabled": true,
"runs": 1000000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"InvalidEdition","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"TooManyRequested","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"address","name":"creatorCore","type":"address"},{"indexed":false,"internalType":"uint256","name":"series","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxSupply","type":"uint256"}],"name":"SeriesCreated","type":"event"},{"inputs":[{"internalType":"address","name":"creatorCore","type":"address"},{"internalType":"uint256","name":"instanceId","type":"uint256"},{"internalType":"uint24","name":"maxSupply_","type":"uint24"},{"internalType":"enum IManifoldERC721Edition.StorageProtocol","name":"storageProtocol","type":"uint8"},{"internalType":"string","name":"location","type":"string"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint16","name":"count","type":"uint16"}],"internalType":"struct IManifoldERC721Edition.Recipient[]","name":"recipients","type":"tuple[]"}],"name":"createSeries","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creatorCore","type":"address"},{"internalType":"uint256","name":"instanceId","type":"uint256"}],"name":"getEditionInfo","outputs":[{"components":[{"internalType":"uint192","name":"firstTokenId","type":"uint192"},{"internalType":"uint8","name":"contractVersion","type":"uint8"},{"internalType":"uint24","name":"totalSupply","type":"uint24"},{"internalType":"uint24","name":"maxSupply","type":"uint24"},{"internalType":"enum IManifoldERC721Edition.StorageProtocol","name":"storageProtocol","type":"uint8"},{"internalType":"string","name":"location","type":"string"}],"internalType":"struct IManifoldERC721Edition.EditionInfo","name":"info","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creatorCore","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"getInstanceIdsForTokens","outputs":[{"internalType":"uint256[]","name":"instanceIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creatorCore","type":"address"},{"internalType":"uint256","name":"instanceId","type":"uint256"}],"name":"getInstanceTokenIds","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creatorCore","type":"address"},{"internalType":"uint256","name":"instanceId","type":"uint256"},{"internalType":"uint24","name":"currentSupply","type":"uint24"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint16","name":"count","type":"uint16"}],"internalType":"struct IManifoldERC721Edition.Recipient[]","name":"recipients","type":"tuple[]"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creatorCore","type":"address"},{"internalType":"uint256","name":"instanceId","type":"uint256"},{"internalType":"enum IManifoldERC721Edition.StorageProtocol","name":"storageProtocol","type":"uint8"},{"internalType":"string","name":"location","type":"string"}],"name":"setTokenURI","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":[{"internalType":"address","name":"creatorCore","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50600160005561330d806100256000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063d4272cd71161005b578063d4272cd71461010a578063e1358e911461011d578063e40ebb6b14610130578063e9dc63751461014357600080fd5b806301ffc9a71461008d57806310ae888f146100b557806318d38411146100d55780635e5ef864146100ea575b600080fd5b6100a061009b3660046126a9565b610163565b60405190151581526020015b60405180910390f35b6100c86100c3366004612717565b61020b565b6040516100ac919061279f565b6100e86100e3366004612839565b6104b0565b005b6100fd6100f83660046128aa565b6106a3565b6040516100ac9190612973565b6100e8610118366004612bb0565b6108f3565b6100e861012b366004612c1a565b610aa3565b6100c861013e3660046128aa565b6110e7565b6101566101513660046128aa565b61150a565b6040516100ac9190612cc1565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe9dc63750000000000000000000000000000000000000000000000000000000014806101f657507fffffffff0000000000000000000000000000000000000000000000000000000082167f873fedd700000000000000000000000000000000000000000000000000000000145b806102055750610205826117f7565b92915050565b60608167ffffffffffffffff81111561022657610226612a3c565b60405190808252806020026020018201604052801561024f578160200160208202803683370190505b50905060005b828110156104a857600084848381811061027157610271612cd4565b9050602002013590508573ffffffffffffffffffffffffffffffffffffffff1663239be317826040518263ffffffff1660e01b81526004016102b591815260200190565b602060405180830381865afa92505050801561030c575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261030991810190612d03565b60015b1561049f573073ffffffffffffffffffffffffffffffffffffffff82160361049d576000808873ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156103b6575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526103b391810190612d20565b60015b156103be5791505b6003821061046d576040517fb4b5b48f0000000000000000000000000000000000000000000000000000000081526004810185905260009073ffffffffffffffffffffffffffffffffffffffff8b169063b4b5b48f90602401602060405180830381865afa158015610434573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104589190612d39565b60181c66ffffffffffffff16915061047b9050565b610477898561188e565b5090505b8086868151811061048e5761048e612cd4565b60200260200101818152505050505b505b50600101610255565b509392505050565b6040517f24d7806c000000000000000000000000000000000000000000000000000000008152336004820152859073ffffffffffffffffffffffffffffffffffffffff8216906324d7806c90602401602060405180830381865afa15801561051c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105409190612d65565b6105d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4d757374206265206f776e6572206f722061646d696e206f662063726561746f60448201527f7220636f6e74726163740000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b60008460038111156105e5576105e56128d6565b0361061c576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006106288787611a88565b8054909150859082907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0100000000000000000000000000000000000000000000000000000000000000836003811115610685576106856128d6565b021790555060018101610699848683612e29565b5050505050505050565b6106dc6040805160c081018252600080825260208201819052918101829052606081018290529060808201908152602001606081525090565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600160209081526040808320858452825291829020825160c081018452815477ffffffffffffffffffffffffffffffffffffffffffffffff8116825260ff7801000000000000000000000000000000000000000000000000820481169483019490945262ffffff79010000000000000000000000000000000000000000000000000082048116958301959095527c01000000000000000000000000000000000000000000000000000000008104909416606082015292909160808401917f010000000000000000000000000000000000000000000000000000000000000090041660038111156107ea576107ea6128d6565b60038111156107fb576107fb6128d6565b815260200160018201805461080f90612d87565b80601f016020809104026020016040519081016040528092919081815260200182805461083b90612d87565b80156108885780601f1061085d57610100808354040283529160200191610888565b820191906000526020600020905b81548152906001019060200180831161086b57829003601f168201915b5050505050815250509050600060038111156108a6576108a66128d6565b816080015160038111156108bc576108bc6128d6565b03610205576040517f720874cf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108fb611af2565b6040517f24d7806c000000000000000000000000000000000000000000000000000000008152336004820152849073ffffffffffffffffffffffffffffffffffffffff8216906324d7806c90602401602060405180830381865afa158015610967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098b9190612d65565b610a17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4d757374206265206f776e6572206f722061646d696e206f662063726561746f60448201527f7220636f6e74726163740000000000000000000000000000000000000000000060648201526084016105c8565b6000610a238686611a88565b805490915062ffffff8581167901000000000000000000000000000000000000000000000000009092041614610a85576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a9186868386611b65565b5050610a9d6001600055565b50505050565b6040517f24d7806c000000000000000000000000000000000000000000000000000000008152336004820152879073ffffffffffffffffffffffffffffffffffffffff8216906324d7806c90602401602060405180830381865afa158015610b0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b339190612d65565b610bbf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4d757374206265206f776e6572206f722061646d696e206f662063726561746f60448201527f7220636f6e74726163740000000000000000000000000000000000000000000060648201526084016105c8565b861580610bd2575066ffffffffffffff87115b80610be0575062ffffff8616155b80610bfc57506000856003811115610bfa57610bfa6128d6565b145b80610c6f5750600073ffffffffffffffffffffffffffffffffffffffff891660009081526001602090815260408083208b84529091529020547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115610c6c57610c6c6128d6565b14155b15610ca6576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008873ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610d2d575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252610d2a91810190612d20565b60015b15610da05760ff811115610d9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f556e737570706f7274656420636f6e74726163742076657273696f6e0000000060448201526064016105c8565b90505b6040518060c00160405280600077ffffffffffffffffffffffffffffffffffffffffffffffff1681526020018260ff168152602001600062ffffff1681526020018862ffffff168152602001876003811115610dfe57610dfe6128d6565b815260200186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093909452505073ffffffffffffffffffffffffffffffffffffffff8c1681526001602090815260408083208d8452825291829020845181549286015193860151606087015162ffffff9081167c0100000000000000000000000000000000000000000000000000000000027fff000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff9190921679010000000000000000000000000000000000000000000000000002167fff000000000000ffffffffffffffffffffffffffffffffffffffffffffffffff60ff9096167801000000000000000000000000000000000000000000000000027fffffffffffffff0000000000000000000000000000000000000000000000000090951677ffffffffffffffffffffffffffffffffffffffffffffffff9093169290921793909317939093169290921717808255608084015191925082907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0100000000000000000000000000000000000000000000000000000000000000836003811115610fd557610fd56128d6565b021790555060a08201516001820190610fee9082612f43565b505050600360ff821610156110365773ffffffffffffffffffffffffffffffffffffffff89166000908152600360209081526040822080546001810182559083529120018890555b6040805133815273ffffffffffffffffffffffffffffffffffffffff8b16602082015290810189905262ffffff881660608201527f739bed52023d4028ee60025b96a4024aacf5aff3162e8c9711084c74d6b8c6139060800160405180910390a18251156110dc5773ffffffffffffffffffffffffffffffffffffffff891660009081526001602090815260408083208b845290915290206110dc908a908a9086611b65565b505050505050505050565b606060006110f58484611a88565b8054909150600090790100000000000000000000000000000000000000000000000000900462ffffff1667ffffffffffffffff81111561113757611137612a3c565b604051908082528060200260200182016040528015611160578160200160208202803683370190505b5092508473ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156111e8575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526111e591810190612d20565b60015b156111f05790505b600381106113ed57815477ffffffffffffffffffffffffffffffffffffffffffffffff1660005b8354790100000000000000000000000000000000000000000000000000900462ffffff168110156113e6576040517f239be3170000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff88169063239be31790602401602060405180830381865afa9250505080156112e7575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526112e491810190612d03565b60015b156113db573073ffffffffffffffffffffffffffffffffffffffff8216036113d9576040517fb4b5b48f0000000000000000000000000000000000000000000000000000000081526004810184905260009073ffffffffffffffffffffffffffffffffffffffff8a169063b4b5b48f90602401602060405180830381865afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b9190612d39565b905066ffffffffffffff601882901c1688036113d757838784815181106113c4576113c4612cd4565b6020026020010181815250508260010192505b505b505b816001019150611217565b5050611502565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600260209081526040808320878452825280832080548251818502810185019093528083529192909190849084015b8282101561147e57838290600052602060002090600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190611438565b5050505090506000805b82518110156114fe5760008382815181106114a5576114a5612cd4565b6020026020010151905060005b81602001518110156114f45781516114cb90829061308c565b8885815181106114dd576114dd612cd4565b6020908102919091010152600193840193016114b2565b5050600101611488565b5050505b505092915050565b606060008373ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611593575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261159091810190612d20565b60015b1561159b5790505b60008060038310611691576040517fb4b5b48f0000000000000000000000000000000000000000000000000000000081526004810186905260009073ffffffffffffffffffffffffffffffffffffffff88169063b4b5b48f90602401602060405180830381865afa158015611614573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116389190612d39565b66ffffffffffffff601882901c16935090506000839003611685576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62ffffff1690506116a1565b61169b868661188e565b90925090505b60006116ad8784611a88565b604080516020810190915260008152909150600282547f0100000000000000000000000000000000000000000000000000000000000000900460ff1660038111156116fa576116fa6128d6565b03611739575060408051808201909152601481527f68747470733a2f2f617277656176652e6e65742f00000000000000000000000060208201526117af565b600382547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115611774576117746128d6565b036117af575060408051808201909152600781527f697066733a2f2f0000000000000000000000000000000000000000000000000060208201525b80826001016117c98560016117c4919061308c565b61237e565b6040516020016117db9392919061309f565b6040516020818303038152906040529550505050505092915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7005caad00000000000000000000000000000000000000000000000000000000148061020557507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610205565b60008060005b73ffffffffffffffffffffffffffffffffffffffff8516600090815260036020526040902054811015611a4e5773ffffffffffffffffffffffffffffffffffffffff851660009081526003602052604081208054839081106118f8576118f8612cd4565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff89168352600282526040808420828552835280842080548251818602810186019093528083529295509092909190849084015b828210156119945783829060005260206000209060020201604051806040016040529081600082015481526020016001820154815250508152602001906001019061194e565b5050505090506000805b8251811015611a3f5760008382815181106119bb576119bb612cd4565b6020026020010151905080600001518910156119d75750611a3f565b805189108015906119f75750602081015181516119f4919061308c565b89105b15611a2557805185908490611a0c908c613185565b611a16919061308c565b97509750505050505050611a81565b6020810151611a34908461308c565b92505060010161199e565b50836001019350505050611894565b506040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9250929050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260016020908152604080832084845290915281209081547f0100000000000000000000000000000000000000000000000000000000000000900460ff1660038111156108bc576108bc6128d6565b600260005403611b5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105c8565b6002600055565b8051600003611ba0576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815462ffffff7c01000000000000000000000000000000000000000000000000000000008204811691611bf391790100000000000000000000000000000000000000000000000000909104166001613198565b62ffffff161115611c30576040517f8d83cdd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81546060906003780100000000000000000000000000000000000000000000000090910460ff161061205157825460009062ffffff79010000000000000000000000000000000000000000000000000082048116917c010000000000000000000000000000000000000000000000000000000090041681835b8651811015611ff1576000878281518110611cc657611cc6612cd4565b60200260200101516020015190508061ffff16600003611d12576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d1c81876131bb565b955062ffffff8416611d3261ffff881687613198565b62ffffff161115611d6f576040517f8d83cdd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008161ffff1667ffffffffffffffff811115611d8e57611d8e612a3c565b604051908082528060200260200182016040528015611db7578160200160208202803683370190505b50905060005b8261ffff16811015611e2557611dd3818661308c565b62ffffff1660188d66ffffffffffffff16901b1766ffffffffffffff16828281518110611e0257611e02612cd4565b69ffffffffffffffffffff90921660209283029190910190910152600101611dbd565b508b73ffffffffffffffffffffffffffffffffffffffff16634278330e8a8581518110611e5457611e54612cd4565b602002602001015160000151836040518363ffffffff1660e01b8152600401611e7e9291906131d6565b6000604051808303816000875af1158015611e9d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611ee39190810190613246565b975082158015611f0c5750895477ffffffffffffffffffffffffffffffffffffffffffffffff16155b15611fdf5777ffffffffffffffffffffffffffffffffffffffffffffffff88600081518110611f3d57611f3d612cd4565b60200260200101511115611f7d576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87600081518110611f9057611f90612cd4565b60209081029190910101518a547fffffffffffffffff0000000000000000000000000000000000000000000000001677ffffffffffffffffffffffffffffffffffffffffffffffff909116178a555b5061ffff169190910190600101611ca9565b50865461ffff851690889060199061202c908490790100000000000000000000000000000000000000000000000000900462ffffff16613198565b92506101000a81548162ffffff021916908362ffffff16021790555050505050612377565b8254600090819062ffffff79010000000000000000000000000000000000000000000000000082048116917c0100000000000000000000000000000000000000000000000000000000900416825b8651811015612369578681815181106120ba576120ba612cd4565b60200260200101516020015161ffff16600003612103576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86818151811061211557612115612cd4565b6020026020010151602001518461212c91906131bb565b935062ffffff821661214261ffff861685613198565b62ffffff16111561217f576040517f8d83cdd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8973ffffffffffffffffffffffffffffffffffffffff1663e00aab4b8883815181106121ad576121ad612cd4565b6020026020010151600001518984815181106121cb576121cb612cd4565b6020026020010151602001516040518363ffffffff1660e01b815260040161221992919073ffffffffffffffffffffffffffffffffffffffff92909216825261ffff16602082015260400190565b6000604051808303816000875af1158015612238573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261227e9190810190613246565b955080600003612361578560008151811061229b5761229b612cd4565b6020908102919091010151885490955077ffffffffffffffffffffffffffffffffffffffffffffffff166000036123615777ffffffffffffffffffffffffffffffffffffffffffffffff85111561231e576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87547fffffffffffffffff0000000000000000000000000000000000000000000000001677ffffffffffffffffffffffffffffffffffffffffffffffff86161788555b60010161209f565b506110dc898989878761243c565b5050505050565b6060600061238b836125c7565b600101905060008167ffffffffffffffff8111156123ab576123ab612a3c565b6040519080825280601f01601f1916602001820160405280156123d5576020820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85049450846123df57509392505050565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600260209081526040808320878452909152812080549091036124b8576040805180820190915283815261ffff83166020808301918252835460018181018655600086815292909220935160029091029093019283559051910155612569565b805460009082906124cb90600190613185565b815481106124db576124db612cd4565b906000526020600020906002020190508381600101548260000154612500919061308c565b03612528578261ffff1681600101600082825461251d919061308c565b909155506125679050565b6040805180820190915284815261ffff841660208083019182528454600181810187556000878152929092209351600290910290930192835590519101555b505b835461ffff83169085906019906125a3908490790100000000000000000000000000000000000000000000000000900462ffffff16613198565b92506101000a81548162ffffff021916908362ffffff160217905550505050505050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612610577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef8100000000831061263c576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061265a57662386f26fc10000830492506010015b6305f5e1008310612672576305f5e100830492506008015b612710831061268657612710830492506004015b60648310612698576064830492506002015b600a83106102055760010192915050565b6000602082840312156126bb57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146126eb57600080fd5b9392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461271457600080fd5b50565b60008060006040848603121561272c57600080fd5b8335612737816126f2565b9250602084013567ffffffffffffffff8082111561275457600080fd5b818601915086601f83011261276857600080fd5b81358181111561277757600080fd5b8760208260051b850101111561278c57600080fd5b6020830194508093505050509250925092565b6020808252825182820181905260009190848201906040850190845b818110156127d7578351835292840192918401916001016127bb565b50909695505050505050565b8035600481106127f257600080fd5b919050565b60008083601f84011261280957600080fd5b50813567ffffffffffffffff81111561282157600080fd5b602083019150836020828501011115611a8157600080fd5b60008060008060006080868803121561285157600080fd5b853561285c816126f2565b945060208601359350612871604087016127e3565b9250606086013567ffffffffffffffff81111561288d57600080fd5b612899888289016127f7565b969995985093965092949392505050565b600080604083850312156128bd57600080fd5b82356128c8816126f2565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60005b83811015612920578181015183820152602001612908565b50506000910152565b60008151808452612941816020860160208601612905565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815277ffffffffffffffffffffffffffffffffffffffffffffffff825116602082015260ff60208301511660408201526000604083015162ffffff80821660608501528060608601511660808501525050608083015160048110612a02577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8060a08401525060a083015160c080840152612a2160e0840182612929565b949350505050565b803562ffffff811681146127f257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715612a8e57612a8e612a3c565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612adb57612adb612a3c565b604052919050565b600067ffffffffffffffff821115612afd57612afd612a3c565b5060051b60200190565b600082601f830112612b1857600080fd5b81356020612b2d612b2883612ae3565b612a94565b82815260069290921b84018101918181019086841115612b4c57600080fd5b8286015b84811015612ba55760408189031215612b695760008081fd5b612b71612a6b565b8135612b7c816126f2565b81528185013561ffff81168114612b935760008081fd5b81860152835291830191604001612b50565b509695505050505050565b60008060008060808587031215612bc657600080fd5b8435612bd1816126f2565b935060208501359250612be660408601612a29565b9150606085013567ffffffffffffffff811115612c0257600080fd5b612c0e87828801612b07565b91505092959194509250565b600080600080600080600060c0888a031215612c3557600080fd5b8735612c40816126f2565b965060208801359550612c5560408901612a29565b9450612c63606089016127e3565b9350608088013567ffffffffffffffff80821115612c8057600080fd5b612c8c8b838c016127f7565b909550935060a08a0135915080821115612ca557600080fd5b50612cb28a828b01612b07565b91505092959891949750929550565b6020815260006126eb6020830184612929565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612d1557600080fd5b81516126eb816126f2565b600060208284031215612d3257600080fd5b5051919050565b600060208284031215612d4b57600080fd5b815169ffffffffffffffffffff811681146126eb57600080fd5b600060208284031215612d7757600080fd5b815180151581146126eb57600080fd5b600181811c90821680612d9b57607f821691505b602082108103612dd4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115612e2457600081815260208120601f850160051c81016020861015612e015750805b601f850160051c820191505b81811015612e2057828155600101612e0d565b5050505b505050565b67ffffffffffffffff831115612e4157612e41612a3c565b612e5583612e4f8354612d87565b83612dda565b6000601f841160018114612ea75760008515612e715750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355612377565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015612ef65786850135825560209485019460019092019101612ed6565b5086821015612f31577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b815167ffffffffffffffff811115612f5d57612f5d612a3c565b612f7181612f6b8454612d87565b84612dda565b602080601f831160018114612fc45760008415612f8e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612e20565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561301157888601518255948401946001909101908401612ff2565b508582101561304d57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102055761020561305d565b6000845160206130b28285838a01612905565b8184019150600086546130c481612d87565b600182811680156130dc576001811461310f5761313b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008416875282151583028701945061313b565b8a6000528560002060005b848110156131335781548982015290830190870161311a565b505082870194505b507f2f0000000000000000000000000000000000000000000000000000000000000084528851955061317286828601878c01612905565b9290940190910198975050505050505050565b818103818111156102055761020561305d565b62ffffff8181168382160190808211156131b4576131b461305d565b5092915050565b61ffff8181168382160190808211156131b4576131b461305d565b60006040820173ffffffffffffffffffffffffffffffffffffffff851683526020604081850152818551808452606086019150828701935060005b8181101561323957845169ffffffffffffffffffff1683529383019391830191600101613211565b5090979650505050505050565b6000602080838503121561325957600080fd5b825167ffffffffffffffff81111561327057600080fd5b8301601f8101851361328157600080fd5b805161328f612b2882612ae3565b81815260059190911b820183019083810190878311156132ae57600080fd5b928401925b828410156132cc578351825292840192908401906132b3565b97965050505050505056fea264697066735822122003e6eed78ba141cfce1d7d17c2a3057c019c31a2bc6c8a1250bcabc6371e6bdc64736f6c63430008110033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063d4272cd71161005b578063d4272cd71461010a578063e1358e911461011d578063e40ebb6b14610130578063e9dc63751461014357600080fd5b806301ffc9a71461008d57806310ae888f146100b557806318d38411146100d55780635e5ef864146100ea575b600080fd5b6100a061009b3660046126a9565b610163565b60405190151581526020015b60405180910390f35b6100c86100c3366004612717565b61020b565b6040516100ac919061279f565b6100e86100e3366004612839565b6104b0565b005b6100fd6100f83660046128aa565b6106a3565b6040516100ac9190612973565b6100e8610118366004612bb0565b6108f3565b6100e861012b366004612c1a565b610aa3565b6100c861013e3660046128aa565b6110e7565b6101566101513660046128aa565b61150a565b6040516100ac9190612cc1565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe9dc63750000000000000000000000000000000000000000000000000000000014806101f657507fffffffff0000000000000000000000000000000000000000000000000000000082167f873fedd700000000000000000000000000000000000000000000000000000000145b806102055750610205826117f7565b92915050565b60608167ffffffffffffffff81111561022657610226612a3c565b60405190808252806020026020018201604052801561024f578160200160208202803683370190505b50905060005b828110156104a857600084848381811061027157610271612cd4565b9050602002013590508573ffffffffffffffffffffffffffffffffffffffff1663239be317826040518263ffffffff1660e01b81526004016102b591815260200190565b602060405180830381865afa92505050801561030c575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261030991810190612d03565b60015b1561049f573073ffffffffffffffffffffffffffffffffffffffff82160361049d576000808873ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156103b6575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526103b391810190612d20565b60015b156103be5791505b6003821061046d576040517fb4b5b48f0000000000000000000000000000000000000000000000000000000081526004810185905260009073ffffffffffffffffffffffffffffffffffffffff8b169063b4b5b48f90602401602060405180830381865afa158015610434573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104589190612d39565b60181c66ffffffffffffff16915061047b9050565b610477898561188e565b5090505b8086868151811061048e5761048e612cd4565b60200260200101818152505050505b505b50600101610255565b509392505050565b6040517f24d7806c000000000000000000000000000000000000000000000000000000008152336004820152859073ffffffffffffffffffffffffffffffffffffffff8216906324d7806c90602401602060405180830381865afa15801561051c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105409190612d65565b6105d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4d757374206265206f776e6572206f722061646d696e206f662063726561746f60448201527f7220636f6e74726163740000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b60008460038111156105e5576105e56128d6565b0361061c576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006106288787611a88565b8054909150859082907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0100000000000000000000000000000000000000000000000000000000000000836003811115610685576106856128d6565b021790555060018101610699848683612e29565b5050505050505050565b6106dc6040805160c081018252600080825260208201819052918101829052606081018290529060808201908152602001606081525090565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600160209081526040808320858452825291829020825160c081018452815477ffffffffffffffffffffffffffffffffffffffffffffffff8116825260ff7801000000000000000000000000000000000000000000000000820481169483019490945262ffffff79010000000000000000000000000000000000000000000000000082048116958301959095527c01000000000000000000000000000000000000000000000000000000008104909416606082015292909160808401917f010000000000000000000000000000000000000000000000000000000000000090041660038111156107ea576107ea6128d6565b60038111156107fb576107fb6128d6565b815260200160018201805461080f90612d87565b80601f016020809104026020016040519081016040528092919081815260200182805461083b90612d87565b80156108885780601f1061085d57610100808354040283529160200191610888565b820191906000526020600020905b81548152906001019060200180831161086b57829003601f168201915b5050505050815250509050600060038111156108a6576108a66128d6565b816080015160038111156108bc576108bc6128d6565b03610205576040517f720874cf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108fb611af2565b6040517f24d7806c000000000000000000000000000000000000000000000000000000008152336004820152849073ffffffffffffffffffffffffffffffffffffffff8216906324d7806c90602401602060405180830381865afa158015610967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098b9190612d65565b610a17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4d757374206265206f776e6572206f722061646d696e206f662063726561746f60448201527f7220636f6e74726163740000000000000000000000000000000000000000000060648201526084016105c8565b6000610a238686611a88565b805490915062ffffff8581167901000000000000000000000000000000000000000000000000009092041614610a85576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a9186868386611b65565b5050610a9d6001600055565b50505050565b6040517f24d7806c000000000000000000000000000000000000000000000000000000008152336004820152879073ffffffffffffffffffffffffffffffffffffffff8216906324d7806c90602401602060405180830381865afa158015610b0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b339190612d65565b610bbf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4d757374206265206f776e6572206f722061646d696e206f662063726561746f60448201527f7220636f6e74726163740000000000000000000000000000000000000000000060648201526084016105c8565b861580610bd2575066ffffffffffffff87115b80610be0575062ffffff8616155b80610bfc57506000856003811115610bfa57610bfa6128d6565b145b80610c6f5750600073ffffffffffffffffffffffffffffffffffffffff891660009081526001602090815260408083208b84529091529020547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115610c6c57610c6c6128d6565b14155b15610ca6576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008873ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610d2d575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252610d2a91810190612d20565b60015b15610da05760ff811115610d9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f556e737570706f7274656420636f6e74726163742076657273696f6e0000000060448201526064016105c8565b90505b6040518060c00160405280600077ffffffffffffffffffffffffffffffffffffffffffffffff1681526020018260ff168152602001600062ffffff1681526020018862ffffff168152602001876003811115610dfe57610dfe6128d6565b815260200186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093909452505073ffffffffffffffffffffffffffffffffffffffff8c1681526001602090815260408083208d8452825291829020845181549286015193860151606087015162ffffff9081167c0100000000000000000000000000000000000000000000000000000000027fff000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff9190921679010000000000000000000000000000000000000000000000000002167fff000000000000ffffffffffffffffffffffffffffffffffffffffffffffffff60ff9096167801000000000000000000000000000000000000000000000000027fffffffffffffff0000000000000000000000000000000000000000000000000090951677ffffffffffffffffffffffffffffffffffffffffffffffff9093169290921793909317939093169290921717808255608084015191925082907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0100000000000000000000000000000000000000000000000000000000000000836003811115610fd557610fd56128d6565b021790555060a08201516001820190610fee9082612f43565b505050600360ff821610156110365773ffffffffffffffffffffffffffffffffffffffff89166000908152600360209081526040822080546001810182559083529120018890555b6040805133815273ffffffffffffffffffffffffffffffffffffffff8b16602082015290810189905262ffffff881660608201527f739bed52023d4028ee60025b96a4024aacf5aff3162e8c9711084c74d6b8c6139060800160405180910390a18251156110dc5773ffffffffffffffffffffffffffffffffffffffff891660009081526001602090815260408083208b845290915290206110dc908a908a9086611b65565b505050505050505050565b606060006110f58484611a88565b8054909150600090790100000000000000000000000000000000000000000000000000900462ffffff1667ffffffffffffffff81111561113757611137612a3c565b604051908082528060200260200182016040528015611160578160200160208202803683370190505b5092508473ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156111e8575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526111e591810190612d20565b60015b156111f05790505b600381106113ed57815477ffffffffffffffffffffffffffffffffffffffffffffffff1660005b8354790100000000000000000000000000000000000000000000000000900462ffffff168110156113e6576040517f239be3170000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff88169063239be31790602401602060405180830381865afa9250505080156112e7575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526112e491810190612d03565b60015b156113db573073ffffffffffffffffffffffffffffffffffffffff8216036113d9576040517fb4b5b48f0000000000000000000000000000000000000000000000000000000081526004810184905260009073ffffffffffffffffffffffffffffffffffffffff8a169063b4b5b48f90602401602060405180830381865afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b9190612d39565b905066ffffffffffffff601882901c1688036113d757838784815181106113c4576113c4612cd4565b6020026020010181815250508260010192505b505b505b816001019150611217565b5050611502565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600260209081526040808320878452825280832080548251818502810185019093528083529192909190849084015b8282101561147e57838290600052602060002090600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190611438565b5050505090506000805b82518110156114fe5760008382815181106114a5576114a5612cd4565b6020026020010151905060005b81602001518110156114f45781516114cb90829061308c565b8885815181106114dd576114dd612cd4565b6020908102919091010152600193840193016114b2565b5050600101611488565b5050505b505092915050565b606060008373ffffffffffffffffffffffffffffffffffffffff1663ffa1ad746040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611593575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261159091810190612d20565b60015b1561159b5790505b60008060038310611691576040517fb4b5b48f0000000000000000000000000000000000000000000000000000000081526004810186905260009073ffffffffffffffffffffffffffffffffffffffff88169063b4b5b48f90602401602060405180830381865afa158015611614573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116389190612d39565b66ffffffffffffff601882901c16935090506000839003611685576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62ffffff1690506116a1565b61169b868661188e565b90925090505b60006116ad8784611a88565b604080516020810190915260008152909150600282547f0100000000000000000000000000000000000000000000000000000000000000900460ff1660038111156116fa576116fa6128d6565b03611739575060408051808201909152601481527f68747470733a2f2f617277656176652e6e65742f00000000000000000000000060208201526117af565b600382547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115611774576117746128d6565b036117af575060408051808201909152600781527f697066733a2f2f0000000000000000000000000000000000000000000000000060208201525b80826001016117c98560016117c4919061308c565b61237e565b6040516020016117db9392919061309f565b6040516020818303038152906040529550505050505092915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7005caad00000000000000000000000000000000000000000000000000000000148061020557507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610205565b60008060005b73ffffffffffffffffffffffffffffffffffffffff8516600090815260036020526040902054811015611a4e5773ffffffffffffffffffffffffffffffffffffffff851660009081526003602052604081208054839081106118f8576118f8612cd4565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff89168352600282526040808420828552835280842080548251818602810186019093528083529295509092909190849084015b828210156119945783829060005260206000209060020201604051806040016040529081600082015481526020016001820154815250508152602001906001019061194e565b5050505090506000805b8251811015611a3f5760008382815181106119bb576119bb612cd4565b6020026020010151905080600001518910156119d75750611a3f565b805189108015906119f75750602081015181516119f4919061308c565b89105b15611a2557805185908490611a0c908c613185565b611a16919061308c565b97509750505050505050611a81565b6020810151611a34908461308c565b92505060010161199e565b50836001019350505050611894565b506040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9250929050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260016020908152604080832084845290915281209081547f0100000000000000000000000000000000000000000000000000000000000000900460ff1660038111156108bc576108bc6128d6565b600260005403611b5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105c8565b6002600055565b8051600003611ba0576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815462ffffff7c01000000000000000000000000000000000000000000000000000000008204811691611bf391790100000000000000000000000000000000000000000000000000909104166001613198565b62ffffff161115611c30576040517f8d83cdd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81546060906003780100000000000000000000000000000000000000000000000090910460ff161061205157825460009062ffffff79010000000000000000000000000000000000000000000000000082048116917c010000000000000000000000000000000000000000000000000000000090041681835b8651811015611ff1576000878281518110611cc657611cc6612cd4565b60200260200101516020015190508061ffff16600003611d12576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d1c81876131bb565b955062ffffff8416611d3261ffff881687613198565b62ffffff161115611d6f576040517f8d83cdd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008161ffff1667ffffffffffffffff811115611d8e57611d8e612a3c565b604051908082528060200260200182016040528015611db7578160200160208202803683370190505b50905060005b8261ffff16811015611e2557611dd3818661308c565b62ffffff1660188d66ffffffffffffff16901b1766ffffffffffffff16828281518110611e0257611e02612cd4565b69ffffffffffffffffffff90921660209283029190910190910152600101611dbd565b508b73ffffffffffffffffffffffffffffffffffffffff16634278330e8a8581518110611e5457611e54612cd4565b602002602001015160000151836040518363ffffffff1660e01b8152600401611e7e9291906131d6565b6000604051808303816000875af1158015611e9d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611ee39190810190613246565b975082158015611f0c5750895477ffffffffffffffffffffffffffffffffffffffffffffffff16155b15611fdf5777ffffffffffffffffffffffffffffffffffffffffffffffff88600081518110611f3d57611f3d612cd4565b60200260200101511115611f7d576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87600081518110611f9057611f90612cd4565b60209081029190910101518a547fffffffffffffffff0000000000000000000000000000000000000000000000001677ffffffffffffffffffffffffffffffffffffffffffffffff909116178a555b5061ffff169190910190600101611ca9565b50865461ffff851690889060199061202c908490790100000000000000000000000000000000000000000000000000900462ffffff16613198565b92506101000a81548162ffffff021916908362ffffff16021790555050505050612377565b8254600090819062ffffff79010000000000000000000000000000000000000000000000000082048116917c0100000000000000000000000000000000000000000000000000000000900416825b8651811015612369578681815181106120ba576120ba612cd4565b60200260200101516020015161ffff16600003612103576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86818151811061211557612115612cd4565b6020026020010151602001518461212c91906131bb565b935062ffffff821661214261ffff861685613198565b62ffffff16111561217f576040517f8d83cdd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8973ffffffffffffffffffffffffffffffffffffffff1663e00aab4b8883815181106121ad576121ad612cd4565b6020026020010151600001518984815181106121cb576121cb612cd4565b6020026020010151602001516040518363ffffffff1660e01b815260040161221992919073ffffffffffffffffffffffffffffffffffffffff92909216825261ffff16602082015260400190565b6000604051808303816000875af1158015612238573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261227e9190810190613246565b955080600003612361578560008151811061229b5761229b612cd4565b6020908102919091010151885490955077ffffffffffffffffffffffffffffffffffffffffffffffff166000036123615777ffffffffffffffffffffffffffffffffffffffffffffffff85111561231e576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87547fffffffffffffffff0000000000000000000000000000000000000000000000001677ffffffffffffffffffffffffffffffffffffffffffffffff86161788555b60010161209f565b506110dc898989878761243c565b5050505050565b6060600061238b836125c7565b600101905060008167ffffffffffffffff8111156123ab576123ab612a3c565b6040519080825280601f01601f1916602001820160405280156123d5576020820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85049450846123df57509392505050565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600260209081526040808320878452909152812080549091036124b8576040805180820190915283815261ffff83166020808301918252835460018181018655600086815292909220935160029091029093019283559051910155612569565b805460009082906124cb90600190613185565b815481106124db576124db612cd4565b906000526020600020906002020190508381600101548260000154612500919061308c565b03612528578261ffff1681600101600082825461251d919061308c565b909155506125679050565b6040805180820190915284815261ffff841660208083019182528454600181810187556000878152929092209351600290910290930192835590519101555b505b835461ffff83169085906019906125a3908490790100000000000000000000000000000000000000000000000000900462ffffff16613198565b92506101000a81548162ffffff021916908362ffffff160217905550505050505050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612610577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef8100000000831061263c576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061265a57662386f26fc10000830492506010015b6305f5e1008310612672576305f5e100830492506008015b612710831061268657612710830492506004015b60648310612698576064830492506002015b600a83106102055760010192915050565b6000602082840312156126bb57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146126eb57600080fd5b9392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461271457600080fd5b50565b60008060006040848603121561272c57600080fd5b8335612737816126f2565b9250602084013567ffffffffffffffff8082111561275457600080fd5b818601915086601f83011261276857600080fd5b81358181111561277757600080fd5b8760208260051b850101111561278c57600080fd5b6020830194508093505050509250925092565b6020808252825182820181905260009190848201906040850190845b818110156127d7578351835292840192918401916001016127bb565b50909695505050505050565b8035600481106127f257600080fd5b919050565b60008083601f84011261280957600080fd5b50813567ffffffffffffffff81111561282157600080fd5b602083019150836020828501011115611a8157600080fd5b60008060008060006080868803121561285157600080fd5b853561285c816126f2565b945060208601359350612871604087016127e3565b9250606086013567ffffffffffffffff81111561288d57600080fd5b612899888289016127f7565b969995985093965092949392505050565b600080604083850312156128bd57600080fd5b82356128c8816126f2565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60005b83811015612920578181015183820152602001612908565b50506000910152565b60008151808452612941816020860160208601612905565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815277ffffffffffffffffffffffffffffffffffffffffffffffff825116602082015260ff60208301511660408201526000604083015162ffffff80821660608501528060608601511660808501525050608083015160048110612a02577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8060a08401525060a083015160c080840152612a2160e0840182612929565b949350505050565b803562ffffff811681146127f257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715612a8e57612a8e612a3c565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612adb57612adb612a3c565b604052919050565b600067ffffffffffffffff821115612afd57612afd612a3c565b5060051b60200190565b600082601f830112612b1857600080fd5b81356020612b2d612b2883612ae3565b612a94565b82815260069290921b84018101918181019086841115612b4c57600080fd5b8286015b84811015612ba55760408189031215612b695760008081fd5b612b71612a6b565b8135612b7c816126f2565b81528185013561ffff81168114612b935760008081fd5b81860152835291830191604001612b50565b509695505050505050565b60008060008060808587031215612bc657600080fd5b8435612bd1816126f2565b935060208501359250612be660408601612a29565b9150606085013567ffffffffffffffff811115612c0257600080fd5b612c0e87828801612b07565b91505092959194509250565b600080600080600080600060c0888a031215612c3557600080fd5b8735612c40816126f2565b965060208801359550612c5560408901612a29565b9450612c63606089016127e3565b9350608088013567ffffffffffffffff80821115612c8057600080fd5b612c8c8b838c016127f7565b909550935060a08a0135915080821115612ca557600080fd5b50612cb28a828b01612b07565b91505092959891949750929550565b6020815260006126eb6020830184612929565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612d1557600080fd5b81516126eb816126f2565b600060208284031215612d3257600080fd5b5051919050565b600060208284031215612d4b57600080fd5b815169ffffffffffffffffffff811681146126eb57600080fd5b600060208284031215612d7757600080fd5b815180151581146126eb57600080fd5b600181811c90821680612d9b57607f821691505b602082108103612dd4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115612e2457600081815260208120601f850160051c81016020861015612e015750805b601f850160051c820191505b81811015612e2057828155600101612e0d565b5050505b505050565b67ffffffffffffffff831115612e4157612e41612a3c565b612e5583612e4f8354612d87565b83612dda565b6000601f841160018114612ea75760008515612e715750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355612377565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015612ef65786850135825560209485019460019092019101612ed6565b5086821015612f31577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b815167ffffffffffffffff811115612f5d57612f5d612a3c565b612f7181612f6b8454612d87565b84612dda565b602080601f831160018114612fc45760008415612f8e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612e20565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561301157888601518255948401946001909101908401612ff2565b508582101561304d57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102055761020561305d565b6000845160206130b28285838a01612905565b8184019150600086546130c481612d87565b600182811680156130dc576001811461310f5761313b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008416875282151583028701945061313b565b8a6000528560002060005b848110156131335781548982015290830190870161311a565b505082870194505b507f2f0000000000000000000000000000000000000000000000000000000000000084528851955061317286828601878c01612905565b9290940190910198975050505050505050565b818103818111156102055761020561305d565b62ffffff8181168382160190808211156131b4576131b461305d565b5092915050565b61ffff8181168382160190808211156131b4576131b461305d565b60006040820173ffffffffffffffffffffffffffffffffffffffff851683526020604081850152818551808452606086019150828701935060005b8181101561323957845169ffffffffffffffffffff1683529383019391830191600101613211565b5090979650505050505050565b6000602080838503121561325957600080fd5b825167ffffffffffffffff81111561327057600080fd5b8301601f8101851361328157600080fd5b805161328f612b2882612ae3565b81815260059190911b820183019083810190878311156132ae57600080fd5b928401925b828410156132cc578351825292840192908401906132b3565b97965050505050505056fea264697066735822122003e6eed78ba141cfce1d7d17c2a3057c019c31a2bc6c8a1250bcabc6371e6bdc64736f6c63430008110033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.