Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
MicroNFTProxyV2
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "../MicroUtilityV4.sol";
import "../erc721/Micro3.sol";
error SaleInactive();
error PurchaseWrongPrice(uint256 correctPrice);
error SoldOut();
error PurchaseTooManyForAddress();
error Canceled();
error IsNotBridge();
error SaleCanNotUpdate();
error InvalidSaleDetail();
error SaleIsNotEnded();
error Unauthorized();
error PresaleMerkleNotApproved();
contract MicroNFTProxyV2 is Micro3, ReentrancyGuard, MicroUtilityV4 {
using Strings for uint256;
using SafeMath for uint256;
uint256 public constant VERSION = 4;
address public owner;
string private _baseURL;
string private _notRevealedURL;
bool private _initialized;
uint224 private _currentTokenId;
struct SaleConfiguration {
uint64 editionSize;
uint16 profitSharing;
address payable fundsRecipient;
uint256 publicSalePrice;
uint32 maxSalePurchasePerAddress;
uint64 publicSaleStart;
uint64 publicSaleEnd;
bytes32 presaleMerkleRoot;
bool cancelable;
}
mapping(address => uint256) public totalMintsByAddress;
SaleConfiguration public saleConfig;
event CrossMint(
address indexed _to,
uint256 _quantity,
uint256 _srcChainId
);
event BridgeIn(address indexed _to, uint256 _dstChainId, uint256 _tokenId);
event BridgeOut(
address indexed _from,
uint256 _dstChainId,
uint256 _tokenId
);
event Purchase(
address indexed to,
uint256 indexed quantity,
uint256 indexed price,
uint256 firstMintedTokenId
);
event OpenMintFinalized(
address indexed sender,
uint256 editionSize,
uint256 timeEnd
);
event AddMerkleProof(
bytes32 indexed merkle
);
event CancelSaleEdition(address indexed sender, uint256 lastTimeUpdated);
event PublicSaleCollection(address indexed sender, uint256 lastTimeUpdated);
event FundsWithdrawn(
address indexed sender,
address indexed fundsRecipient,
uint256 fund
);
modifier onlyOwner() {
require(owner == _msgSender());
_;
}
modifier onlyBridge() {
if (!microManager.microBridge(_msgSender())) {
revert IsNotBridge();
}
_;
}
modifier onlyCancelable() {
if (saleConfig.cancelable) {
revert Canceled();
}
_;
}
modifier canMintTokens(uint256 quantity) {
if (
saleConfig.editionSize != 0 &&
quantity + _currentTokenId > saleConfig.editionSize
) {
revert SoldOut();
}
_;
}
modifier onlyPublicSaleActive() {
if (
!(saleConfig.publicSaleStart <= block.timestamp &&
saleConfig.publicSaleEnd > block.timestamp)
) {
revert SaleInactive();
}
_;
}
function init(bytes memory initPayload) external returns (bool) {
if (_initialized) {
revert Unauthorized();
}
(
string memory _url,
string memory _singleUrl,
string memory _name,
string memory _symbol,
address _owner,
address _manager
) = abi.decode(
initPayload,
(string, string, string, string, address, address)
);
owner = _owner;
_setManager(_manager);
_baseURL = _url;
_notRevealedURL = _singleUrl;
_init(_name, _symbol);
_initialized = true;
return true;
}
function tokenURI(uint256 tokenId)
public
view
virtual
override
returns (string memory)
{
_requireOwned(tokenId);
if (bytes(_notRevealedURL).length > 0) {
return _notRevealedURL;
}
return
bytes(_baseURL).length > 0
? string(
abi.encodePacked(_baseURL, tokenId.toString(), ".json")
)
: "";
}
function setBaseURI(string memory _newURI) external onlyOwner {
_setBaseURI(_newURI);
}
function setNotRevealedURI(string memory _newURI) external onlyOwner {
_notRevealedURL = _newURI;
}
/**
* Owner, Admin FUNCTIONS
* non state changing
*/
function transferOwnership(address newOwner) external onlyOwner {
if(newOwner == address(0)){
revert Unauthorized();
}
_setOwner(newOwner);
}
function adminMint(address recipient, uint256 quantity)
external
onlyOwner
canMintTokens(quantity)
returns (uint256)
{
_mintNFTs(recipient, quantity);
return _currentTokenId;
}
function setSaleDetail(bytes memory initPayload)
external
onlyCancelable
onlyOwner
{
if (
saleConfig.publicSaleStart != 0 &&
block.timestamp > saleConfig.publicSaleStart
) {
revert SaleCanNotUpdate();
}
SaleConfiguration memory config = abi.decode(
initPayload,
(SaleConfiguration)
);
if (
config.publicSaleStart <= block.timestamp ||
config.publicSaleEnd <= config.publicSaleStart ||
config.profitSharing > 50 ||
config.fundsRecipient == address(0)
) {
revert InvalidSaleDetail();
}
saleConfig = SaleConfiguration({
editionSize: config.editionSize,
profitSharing: config.profitSharing,
fundsRecipient: config.fundsRecipient,
publicSalePrice: config.publicSalePrice,
maxSalePurchasePerAddress: config.maxSalePurchasePerAddress,
publicSaleStart: config.publicSaleStart,
publicSaleEnd: config.publicSaleEnd,
presaleMerkleRoot: config.presaleMerkleRoot,
cancelable: false
});
emit PublicSaleCollection(_msgSender(), block.timestamp);
}
function setMerkleProof(bytes32 _merkle) external onlyCancelable onlyOwner {
saleConfig.presaleMerkleRoot = _merkle;
emit AddMerkleProof(_merkle);
}
function finalizeOpenEdition() external onlyCancelable onlyOwner {
saleConfig.editionSize = uint64(_currentTokenId);
saleConfig.publicSaleEnd = uint64(block.timestamp);
emit OpenMintFinalized(
_msgSender(),
saleConfig.editionSize,
block.timestamp
);
}
function cancelSaleEdition() external onlyCancelable onlyOwner {
if (block.timestamp > saleConfig.publicSaleEnd) {
revert SaleIsNotEnded();
}
saleConfig.cancelable = true;
emit CancelSaleEdition(_msgSender(), block.timestamp);
}
/**
* EXTERNAL FUNCTIONS
* state changing
*/
function purchase(uint256 quantity)
external
payable
onlyCancelable
canMintTokens(quantity)
onlyPublicSaleActive
nonReentrant
returns (uint256)
{
if(saleConfig.presaleMerkleRoot != bytes32(0)){
revert Unauthorized();
}
address minter = _msgSender();
uint256 salePrice = saleConfig.publicSalePrice.mul(quantity);
uint256 protocolFee = getMicroFeeWei(quantity);
uint256 totalFee = salePrice.add(protocolFee);
_isMinting(minter, msg.value, totalFee, quantity);
_payoutMicroFee(protocolFee);
_payoutFundingRaise(salePrice);
_payoutRemainder(minter, msg.value.sub(totalFee));
emit Purchase({
to: minter,
quantity: quantity,
price: saleConfig.publicSalePrice,
firstMintedTokenId: _currentTokenId
});
return _currentTokenId;
}
function purchasePresale(uint256 quantity, bytes32[] calldata merkleProof)
external
payable
onlyCancelable
canMintTokens(quantity)
onlyPublicSaleActive
nonReentrant
returns (uint256)
{
address minter = _msgSender();
if (
!MerkleProof.verify(
merkleProof,
saleConfig.presaleMerkleRoot,
keccak256(abi.encodePacked(minter))
)
) {
revert PresaleMerkleNotApproved();
}
uint256 salePrice = saleConfig.publicSalePrice.mul(quantity);
uint256 protocolFee = getMicroFeeWei(quantity);
uint256 totalFee = salePrice.add(protocolFee);
_isMinting(minter, msg.value, totalFee, quantity);
_payoutMicroFee(protocolFee);
_payoutFundingRaise(salePrice);
_payoutRemainder(minter, msg.value.sub(totalFee));
emit Purchase({
to: minter,
quantity: quantity,
price: saleConfig.publicSalePrice,
firstMintedTokenId: _currentTokenId
});
return _currentTokenId;
}
function bridgeOut(
address _from,
uint64 _dstChainId,
uint256 _tokenId
) external onlyBridge {
_burn(_tokenId);
emit BridgeOut(_from, _dstChainId, _tokenId);
}
function bridgeIn(
address _toAddress,
uint64 _dstChainId,
uint256 _tokenId
) external onlyBridge {
_safeMint(_toAddress, _tokenId);
emit BridgeIn(_toAddress, _dstChainId, _tokenId);
}
function crossMint(
address _toAddress,
address _fundAddress,
uint256 _quantity,
uint256 _priceCheck,
uint64 _srcChainId
)
external
onlyBridge
canMintTokens(_quantity)
onlyCancelable
onlyPublicSaleActive
{
if (saleConfig.fundsRecipient != _fundAddress) {
revert Unauthorized();
}
_isMinting(_toAddress, _priceCheck, saleConfig.publicSalePrice.mul(_quantity), _quantity);
emit CrossMint(_toAddress, _quantity, _srcChainId);
}
/**
* INTERNAL FUNCTIONS
* state changing
*/
function _mintNFTs(address recipient, uint256 quantity) internal {
for (uint256 i; i < quantity; ) {
_currentTokenId += 1;
_safeMint(
recipient,
uint256(
bytes32(
abi.encodePacked(
uint32(block.chainid),
uint224(_currentTokenId)
)
)
)
);
unchecked {
++i;
}
}
}
function _payoutFundingRaise(uint256 totalPurchase)
internal
returns (bool)
{
if (saleConfig.fundsRecipient == address(0) || totalPurchase == 0) {
return false;
}
_payoutRemainder(saleConfig.fundsRecipient, totalPurchase);
emit FundsWithdrawn(
_msgSender(),
saleConfig.fundsRecipient,
totalPurchase
);
return true;
}
function _isMinting(address toAddress, uint256 payableValue, uint256 totalFee, uint256 quantity)
internal
{
if(quantity == 0) {
revert Unauthorized();
}
if (payableValue < totalFee) {
revert PurchaseWrongPrice(totalFee);
}
if (
saleConfig.maxSalePurchasePerAddress != 0 &&
totalMintsByAddress[toAddress].add(quantity) >
saleConfig.maxSalePurchasePerAddress
) {
revert PurchaseTooManyForAddress();
}
_mintNFTs(toAddress, quantity);
totalMintsByAddress[toAddress] += quantity;
}
function _setBaseURI(string memory _newURI) internal {
_baseURL = _newURI;
}
function _setOwner(address newOwner) internal {
owner = newOwner;
}
}// SPDX-License-Identifier: MIT
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 make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// 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
pragma solidity ^0.8.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev These functions deal with verification of Merkle Trees proofs.
*
* The proofs can be generated using the JavaScript library
* https://github.com/miguelmota/merkletreejs[merkletreejs].
* Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
*
* See `test/utils/cryptography/MerkleProof.test.js` for some examples.
*/
library MerkleProof {
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*/
function verify(
bytes32[] memory proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
if (computedHash <= proofElement) {
// Hash(current computed hash + current element of the proof)
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
} else {
// Hash(current element of the proof + current computed hash)
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
}
}
// Check if the computed hash (root) is equal to the provided root
return computedHash == root;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.13;
import {IERC165} from "./utils/IERC165.sol";
/**
* @dev Required interface of an ERC-721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC-721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
* {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {MRC721} from "./MRC721.sol";
import {IERC721Enumerable} from "./utils/IERC721Enumerable.sol";
import {IERC165} from "./utils/ERC165.sol";
abstract contract Micro3 is MRC721, IERC721Enumerable {
mapping(address => mapping(uint256 => uint256))
private _ownedTokens;
mapping(uint256 => uint256) private _ownedTokensIndex;
uint256[] private _allTokens;
mapping(uint256 => uint256) private _allTokensIndex;
/**
* @dev An `owner`'s token query was out of bounds for `index`.
*
* NOTE: The owner being `address(0)` indicates a global out of bounds index.
*/
error ERC721OutOfBoundsIndex(address owner, uint256 index);
/**
* @dev Batch mint is not allowed.
*/
error ERC721EnumerableForbiddenBatchMint();
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(
bytes4 interfaceId
) public view virtual override(IERC165, MRC721) returns (bool) {
return
interfaceId == type(IERC721Enumerable).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(
address owner,
uint256 index
) public view virtual returns (uint256) {
if (index >= balanceOf(owner)) {
revert ERC721OutOfBoundsIndex(owner, index);
}
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual returns (uint256) {
if (index >= totalSupply()) {
revert ERC721OutOfBoundsIndex(address(0), index);
}
return _allTokens[index];
}
/**
* @dev See {ERC721-_update}.
*/
function _update(
address to,
uint256 tokenId,
address auth
) internal virtual override returns (address) {
address previousOwner = super._update(to, tokenId, auth);
if (previousOwner == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_removeTokenFromOwnerEnumeration(previousOwner, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_addTokenToOwnerEnumeration(to, tokenId);
}
return previousOwner;
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = balanceOf(to) - 1;
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(
address from,
uint256 tokenId
) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = balanceOf(from);
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
/**
* See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch
*/
function _increaseBalance(
address account,
uint128 amount
) internal virtual override {
if (amount > 0) {
revert ERC721EnumerableForbiddenBatchMint();
}
super._increaseBalance(account, amount);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.13;
import {IERC721} from "./IERC721.sol";
import {IERC721Metadata} from "./utils/IERC721Metadata.sol";
import {ERC721Utils} from "./utils/ERC721Utils.sol";
import {IERC165, ERC165} from "./utils/ERC165.sol";
import {IERC721Errors} from "./utils/IERC721Errors.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/Context.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC-721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
abstract contract MRC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
mapping(uint256 => address) private _owners;
mapping(address => uint256) private _balances;
mapping(uint256 => address) private _tokenApprovals;
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
function _init(string memory name_, string memory symbol_) internal {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual returns (uint256) {
if (owner == address(0)) {
revert ERC721InvalidOwner(address(0));
}
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual returns (address) {
return _requireOwned(tokenId);
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
_requireOwned(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual {
_approve(to, tokenId, _msgSender());
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual returns (address) {
_requireOwned(tokenId);
return _getApproved(tokenId);
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
// Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists
// (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.
address previousOwner = _update(to, tokenId, _msgSender());
if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
transferFrom(from, to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*
* IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the
* core ERC-721 logic MUST be matched with the use of {_increaseBalance} to keep balances
* consistent with ownership. The invariant to preserve is that for any address `a` the value returned by
* `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.
*/
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
/**
* @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.
*/
function _getApproved(uint256 tokenId) internal view virtual returns (address) {
return _tokenApprovals[tokenId];
}
/**
* @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
* particular (ignoring whether it is owned by `owner`).
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
return
spender != address(0) &&
(owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
}
/**
* @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.
* Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets
* the `spender` for the specific `tokenId`.
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {
if (!_isAuthorized(owner, spender, tokenId)) {
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else {
revert ERC721InsufficientApproval(spender, tokenId);
}
}
}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that
* a uint256 would ever overflow from increments when these increments are bounded to uint128 values.
*
* WARNING: Increasing an account's balance using this function tends to be paired with an override of the
* {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership
* remain consistent with one another.
*/
function _increaseBalance(address account, uint128 value) internal virtual {
unchecked {
_balances[account] += value;
}
}
/**
* @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner
* (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that
* `auth` is either the owner of the token, or approved to operate on the token (by the owner).
*
* Emits a {Transfer} event.
*
* NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.
*/
function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
address from = _ownerOf(tokenId);
// Perform (optional) operator check
if (auth != address(0)) {
_checkAuthorized(from, auth, tokenId);
}
// Execute the update
if (from != address(0)) {
// Clear approval. No need to re-authorize or emit the Approval event
_approve(address(0), tokenId, address(0), false);
unchecked {
_balances[from] -= 1;
}
}
if (to != address(0)) {
unchecked {
_balances[to] += 1;
}
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
return from;
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner != address(0)) {
revert ERC721InvalidSender(address(0));
}
}
/**
* @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
_mint(to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), address(0), to, tokenId, data);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal {
address previousOwner = _update(address(0), tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(address from, address to, uint256 tokenId) internal {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients
* are aware of the ERC-721 standard to prevent tokens from being forever locked.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is like {safeTransferFrom} in the sense that it invokes
* {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `tokenId` token must exist and be owned by `from`.
* - `to` cannot be the zero address.
* - `from` cannot be the zero address.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(address from, address to, uint256 tokenId) internal {
_safeTransfer(from, to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
_transfer(from, to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is
* either the owner of the token, or approved to operate on all tokens held by this owner.
*
* Emits an {Approval} event.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address to, uint256 tokenId, address auth) internal {
_approve(to, tokenId, auth, true);
}
/**
* @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not
* emitted in the context of transfers.
*/
function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {
// Avoid reading the owner unless necessary
if (emitEvent || auth != address(0)) {
address owner = _requireOwned(tokenId);
// We do not use _isAuthorized because single-token approvals should not be able to call approve
if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {
revert ERC721InvalidApprover(auth);
}
if (emitEvent) {
emit Approval(owner, to, tokenId);
}
}
_tokenApprovals[tokenId] = to;
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Requirements:
* - operator can't be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
if (operator == address(0)) {
revert ERC721InvalidOperator(operator);
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).
* Returns the owner.
*
* Overrides to ownership logic should be done to {_ownerOf}.
*/
function _requireOwned(uint256 tokenId) internal view returns (address) {
address owner = _ownerOf(tokenId);
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
return owner;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.13;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 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);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {IERC721Receiver} from "./IERC721Receiver.sol";
import {IERC721Errors} from "./IERC721Errors.sol";
/**
* @dev Library that provide common ERC-721 utility functions.
*
* See https://eips.ethereum.org/EIPS/eip-721[ERC-721].
*/
library ERC721Utils {
/**
* @dev Performs an acceptance check for the provided `operator` by calling {IERC721-onERC721Received}
* on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
*
* The acceptance call is not executed and treated as a no-op if the target address is doesn't contain code (i.e. an EOA).
* Otherwise, the recipient must implement {IERC721Receiver-onERC721Received} and return the acceptance magic value to accept
* the transfer.
*/
function checkOnERC721Received(
address operator,
address from,
address to,
uint256 tokenId,
bytes memory data
) internal {
if (to.code.length > 0) {
try IERC721Receiver(to).onERC721Received(operator, from, tokenId, data) returns (bytes4 retval) {
if (retval != IERC721Receiver.onERC721Received.selector) {
// Token rejected
revert IERC721Errors.ERC721InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
// non-IERC721Receiver implementer
revert IERC721Errors.ERC721InvalidReceiver(to);
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.13;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* 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[ERC 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
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.13;
import {IERC721} from "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.13;
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.13;
import {IERC721} from "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.13;
/**
* @title ERC-721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC-721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be
* reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.5.0;
interface IMicroManager {
function microBridge(address _address) external view returns (bool);
function treasuryAddress() external view returns (address);
function microProtocolFee() external view returns (uint256);
function oracleAddress() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
interface IPriceOracle {
function convertUsdToWei(uint256 usdAmount) external view returns (uint256 weiAmount);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import {IPriceOracle} from "./interfaces/IPriceOracle.sol";
import {IMicroManager} from "./interfaces/IMicroManager.sol";
error PaymentFailed();
contract MicroUtilityV4 {
using SafeMath for uint256;
IMicroManager public microManager;
uint256 private constant STATIC_GAS_LIMIT = 210_000;
event FeePayout(
uint256 MicroMintFeeWei,
address MicroFeeRecipient,
bool success
);
/**
* PUBLIC FUNCTIONS
* state changing
*/
function getMicroFeeWei(uint256 quantity) public view returns (uint256) {
if (quantity == 0) {
return 0;
}
return
IPriceOracle(microManager.oracleAddress()).convertUsdToWei(
microManager.microProtocolFee().mul(quantity)
);
}
function _payoutMicroFee(uint256 microProtocolFee) internal {
address treasury = microManager.treasuryAddress();
_payoutRemainder(treasury, microProtocolFee);
emit FeePayout(microProtocolFee, treasury, true);
}
function _setManager(address _manager) internal {
microManager = IMicroManager(_manager);
}
function _payoutRemainder(address recipient, uint256 value) internal {
if (value > 0) {
(bool success, ) = payable(recipient).call{
value: value,
gas: gasleft() > STATIC_GAS_LIMIT ? STATIC_GAS_LIMIT : gasleft()
}("");
if (!success) {
revert PaymentFailed();
}
}
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"Canceled","type":"error"},{"inputs":[],"name":"ERC721EnumerableForbiddenBatchMint","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"ERC721OutOfBoundsIndex","type":"error"},{"inputs":[],"name":"InvalidSaleDetail","type":"error"},{"inputs":[],"name":"IsNotBridge","type":"error"},{"inputs":[],"name":"PaymentFailed","type":"error"},{"inputs":[],"name":"PresaleMerkleNotApproved","type":"error"},{"inputs":[],"name":"PurchaseTooManyForAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"correctPrice","type":"uint256"}],"name":"PurchaseWrongPrice","type":"error"},{"inputs":[],"name":"SaleCanNotUpdate","type":"error"},{"inputs":[],"name":"SaleInactive","type":"error"},{"inputs":[],"name":"SaleIsNotEnded","type":"error"},{"inputs":[],"name":"SoldOut","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"merkle","type":"bytes32"}],"name":"AddMerkleProof","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_dstChainId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"BridgeIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"uint256","name":"_dstChainId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"BridgeOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"lastTimeUpdated","type":"uint256"}],"name":"CancelSaleEdition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_quantity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_srcChainId","type":"uint256"}],"name":"CrossMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"MicroMintFeeWei","type":"uint256"},{"indexed":false,"internalType":"address","name":"MicroFeeRecipient","type":"address"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"FeePayout","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"fundsRecipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"fund","type":"uint256"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"editionSize","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timeEnd","type":"uint256"}],"name":"OpenMintFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"lastTimeUpdated","type":"uint256"}],"name":"PublicSaleCollection","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"quantity","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"firstMintedTokenId","type":"uint256"}],"name":"Purchase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"adminMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_toAddress","type":"address"},{"internalType":"uint64","name":"_dstChainId","type":"uint64"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"bridgeIn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint64","name":"_dstChainId","type":"uint64"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"bridgeOut","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelSaleEdition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_toAddress","type":"address"},{"internalType":"address","name":"_fundAddress","type":"address"},{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"uint256","name":"_priceCheck","type":"uint256"},{"internalType":"uint64","name":"_srcChainId","type":"uint64"}],"name":"crossMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finalizeOpenEdition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"getMicroFeeWei","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"initPayload","type":"bytes"}],"name":"init","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"microManager","outputs":[{"internalType":"contract IMicroManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"purchase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"purchasePresale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"saleConfig","outputs":[{"internalType":"uint64","name":"editionSize","type":"uint64"},{"internalType":"uint16","name":"profitSharing","type":"uint16"},{"internalType":"address payable","name":"fundsRecipient","type":"address"},{"internalType":"uint256","name":"publicSalePrice","type":"uint256"},{"internalType":"uint32","name":"maxSalePurchasePerAddress","type":"uint32"},{"internalType":"uint64","name":"publicSaleStart","type":"uint64"},{"internalType":"uint64","name":"publicSaleEnd","type":"uint64"},{"internalType":"bytes32","name":"presaleMerkleRoot","type":"bytes32"},{"internalType":"bool","name":"cancelable","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_merkle","type":"bytes32"}],"name":"setMerkleProof","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newURI","type":"string"}],"name":"setNotRevealedURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"initPayload","type":"bytes"}],"name":"setSaleDetail","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalMintsByAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b506001600a556134f0806100256000396000f3fe60806040526004361061020f5760003560e01c806370a0823111610118578063c87b56dd116100a0578063efef39a11161006f578063efef39a1146106ca578063f2c4ce1e146106dd578063f2fde38b146106fd578063f5a0384c1461071d578063ffa1ad741461073257600080fd5b8063c87b56dd1461064a578063e58306f91461066a578063e985e9c51461068a578063ed50d883146106aa57600080fd5b80639123f01e116100e75780639123f01e146105a857806394847d62146105d557806395d89b41146105f5578063a22cb4651461060a578063b88d4fde1461062a57600080fd5b806370a082311461046c578063867589121461048c5780638da5cb5b146104ac57806390aa0b0f146104cc57600080fd5b80632f745c591161019b5780634f6ccce71161016a5780634f6ccce7146103d957806355f804b3146103f9578063616985ed146104195780636352211e1461043957806370970d561461045957600080fd5b80632f745c591461036457806341e96eb11461038457806342842e0e146103995780634ddf47d4146103b957600080fd5b80630e21ea06116101e25780630e21ea06146102c55780630e46c9a6146102e557806318160ddd1461030557806323b872dd146103245780632cde12151461034457600080fd5b806301ffc9a71461021457806306fdde0314610249578063081812fc1461026b578063095ea7b3146102a3575b600080fd5b34801561022057600080fd5b5061023461022f366004612b10565b610747565b60405190151581526020015b60405180910390f35b34801561025557600080fd5b5061025e610772565b6040516102409190612b85565b34801561027757600080fd5b5061028b610286366004612b98565b610804565b6040516001600160a01b039091168152602001610240565b3480156102af57600080fd5b506102c36102be366004612bc6565b61082d565b005b3480156102d157600080fd5b50600b5461028b906001600160a01b031681565b3480156102f157600080fd5b506102c3610300366004612c07565b61083c565b34801561031157600080fd5b506008545b604051908152602001610240565b34801561033057600080fd5b506102c361033f366004612c48565b61092f565b34801561035057600080fd5b506102c361035f366004612c07565b6109bf565b34801561037057600080fd5b5061031661037f366004612bc6565b610aaa565b34801561039057600080fd5b506102c3610b0f565b3480156103a557600080fd5b506102c36103b4366004612c48565b610bf1565b3480156103c557600080fd5b506102346103d4366004612d6c565b610c11565b3480156103e557600080fd5b506103166103f4366004612b98565b610cf5565b34801561040557600080fd5b506102c3610414366004612da0565b610d4e565b34801561042557600080fd5b50610316610434366004612b98565b610d71565b34801561044557600080fd5b5061028b610454366004612b98565b610ee8565b610316610467366004612de8565b610ef3565b34801561047857600080fd5b50610316610487366004612e66565b611192565b34801561049857600080fd5b506102c36104a7366004612b98565b6111da565b3480156104b857600080fd5b50600c5461028b906001600160a01b031681565b3480156104d857600080fd5b5060115460125460135460145460155461053b946001600160401b0380821695600160401b830461ffff1695600160501b9093046001600160a01b031694909363ffffffff841693600160201b8104841693600160601b90910416919060ff1689565b604080516001600160401b039a8b16815261ffff90991660208a01526001600160a01b0390971696880196909652606087019490945263ffffffff9092166080860152851660a08501529390931660c083015260e082019290925290151561010082015261012001610240565b3480156105b457600080fd5b506103166105c3366004612e66565b60106020526000908152604090205481565b3480156105e157600080fd5b506102c36105f0366004612d6c565b611248565b34801561060157600080fd5b5061025e6114dd565b34801561061657600080fd5b506102c3610625366004612e91565b6114ec565b34801561063657600080fd5b506102c3610645366004612eca565b6114f7565b34801561065657600080fd5b5061025e610665366004612b98565b61150f565b34801561067657600080fd5b50610316610685366004612bc6565b611620565b34801561069657600080fd5b506102346106a5366004612f35565b6116be565b3480156106b657600080fd5b506102c36106c5366004612f63565b6116ec565b6103166106d8366004612b98565b6118fd565b3480156106e957600080fd5b506102c36106f8366004612da0565b611b1f565b34801561070957600080fd5b506102c3610718366004612e66565b611b49565b34801561072957600080fd5b506102c3611ba4565b34801561073e57600080fd5b50610316600481565b60006001600160e01b0319821663780e9d6360e01b148061076c575061076c82611c60565b92915050565b60606000805461078190612fc2565b80601f01602080910402602001604051908101604052809291908181526020018280546107ad90612fc2565b80156107fa5780601f106107cf576101008083540402835291602001916107fa565b820191906000526020600020905b8154815290600101906020018083116107dd57829003601f168201915b5050505050905090565b600061080f82611cb0565b506000828152600460205260409020546001600160a01b031661076c565b610838828233611ce9565b5050565b600b546001600160a01b0316631222cea6336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610892573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b6919061300c565b6108d3576040516311ebaa2760e11b815260040160405180910390fd5b6108dc81611cf6565b604080516001600160401b0384168152602081018390526001600160a01b038516917f40b70b451dc629fad6a565da866d93b8c178df2cb218fc32f6af8041165309c191015b60405180910390a2505050565b6001600160a01b03821661095e57604051633250574960e11b8152600060048201526024015b60405180910390fd5b600061096b838333611d31565b9050836001600160a01b0316816001600160a01b0316146109b9576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610955565b50505050565b600b546001600160a01b0316631222cea6336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a39919061300c565b610a56576040516311ebaa2760e11b815260040160405180910390fd5b610a608382611e06565b604080516001600160401b0384168152602081018390526001600160a01b038516917f780140c12a9c67a3a283c7f237e9577318a108e1dfdeb57542a4655c89be38b79101610922565b6000610ab583611192565b8210610ae65760405163295f44f760e21b81526001600160a01b038416600482015260248101839052604401610955565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b60155460ff1615610b3357604051631afb0ae560e01b815260040160405180910390fd5b600c546001600160a01b03163314610b4a57600080fd5b600f54601180546001600160401b03610100909304831667ffffffffffffffff199091161790556013805442909216600160601b0267ffffffffffffffff60601b19909216919091179055610b9c3390565b601154604080516001600160401b0390921682524260208301526001600160a01b0392909216917fc0786675f6128bc0b8e886ad509fa0cc374ec4c3efe21e941920ea683bd1741d91015b60405180910390a2565b610c0c838383604051806020016040528060008152506114f7565b505050565b600f5460009060ff1615610c37576040516282b42960e81b815260040160405180910390fd5b60008060008060008087806020019051810190610c549190613079565b600c80546001600160a01b0384166001600160a01b0319909116179055949a50929850909650945092509050610ca781600b80546001600160a01b039092166001600160a01b0319909216919091179055565b8551610cba90600d906020890190612a61565b508451610cce90600e906020880190612a61565b50610cd98484611e20565b5050600f805460ff191660019081179091559695505050505050565b6000610d0060085490565b8210610d295760405163295f44f760e21b81526000600482015260248101839052604401610955565b60088281548110610d3c57610d3c613145565b90600052602060002001549050919050565b600c546001600160a01b03163314610d6557600080fd5b610d6e81611e47565b50565b600081600003610d8357506000919050565b600b60009054906101000a90046001600160a01b03166001600160a01b031663a89ae4ba6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfa919061315b565b6001600160a01b031663f5d78161610e8984600b60009054906101000a90046001600160a01b03166001600160a01b0316630c1119bb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e839190613178565b90611e5a565b6040518263ffffffff1660e01b8152600401610ea791815260200190565b602060405180830381865afa158015610ec4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076c9190613178565b600061076c82611cb0565b60155460009060ff1615610f1a57604051631afb0ae560e01b815260040160405180910390fd5b60115484906001600160401b031615801590610f5d5750601154600f546001600160401b0390911690610f5b9061010090046001600160e01b0316836131a7565b115b15610f7b576040516352df9fe560e01b815260040160405180910390fd5b60135442600160201b9091046001600160401b031611801590610fb0575060135442600160601b9091046001600160401b0316115b610fcd57604051630fe219dd60e21b815260040160405180910390fd5b6002600a540361101f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610955565b6002600a55600033905061109f858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506014546040516bffffffffffffffffffffffff19606088901b166020820152909250603401905060405160208183030381529060405280519060200120611e6d565b6110bc576040516346cabb7560e01b815260040160405180910390fd5b6012546000906110cc9088611e5a565b905060006110d988610d71565b905060006110e78383611f1c565b90506110f58434838c611f28565b6110fe8261200d565b611107836120d3565b5061111b84611116348461217b565b612187565b601254600f546040516101009091046001600160e01b031681528a906001600160a01b038716907f5bc97d73357ac0d035d4b9268a69240988a5776b8a4fcced3dbc223960123f409060200160405180910390a45050600f546001600a5561010090046001600160e01b0316979650505050505050565b60006001600160a01b0382166111be576040516322718ad960e21b815260006004820152602401610955565b506001600160a01b031660009081526003602052604090205490565b60155460ff16156111fe57604051631afb0ae560e01b815260040160405180910390fd5b600c546001600160a01b0316331461121557600080fd5b601481905560405181907fac0e7be7f0391f6f84d2d6c5c9300942e4d7e7a79629f63f0078050c21300d9e90600090a250565b60155460ff161561126c57604051631afb0ae560e01b815260040160405180910390fd5b600c546001600160a01b0316331461128357600080fd5b601354600160201b90046001600160401b0316158015906112b55750601354600160201b90046001600160401b031642115b156112d357604051630571129f60e51b815260040160405180910390fd5b6000818060200190518101906112e991906131f0565b9050428160a001516001600160401b031611158061132157508060a001516001600160401b03168160c001516001600160401b031611155b8061133457506032816020015161ffff16115b8061134a575060408101516001600160a01b0316155b15611368576040516371dff4bd60e11b815260040160405180910390fd5b604080516101208101825282516001600160401b0390811680835260208086015161ffff16908401819052858501516001600160a01b031694840185905260608087015190850181905260808088015163ffffffff1690860181905260a080890151861690870181905260c0808a015190961695870186905260e0808a01519088018190526000610100909801979097526011805469ffffffffffffffffffff1916909517600160401b909402939093177fffff0000000000000000000000000000000000000000ffffffffffffffffffff16600160501b90970296909617909255601291909155601380546bffffffffffffffffffffffff1916909417600160201b9091021767ffffffffffffffff60601b1916600160601b909102179091556014556015805460ff19169055336001600160a01b03167f7f5a7a2bf5c04c7c8759c017a2991abaf03db78e2595e806fe7b6add4dffe4b6426040516114d191815260200190565b60405180910390a25050565b60606001805461078190612fc2565b610838338383612216565b61150284848461092f565b6109b933858585856122b5565b606061151a82611cb0565b506000600e805461152a90612fc2565b905011156115c457600e805461153f90612fc2565b80601f016020809104026020016040519081016040528092919081815260200182805461156b90612fc2565b80156115b85780601f1061158d576101008083540402835291602001916115b8565b820191906000526020600020905b81548152906001019060200180831161159b57829003601f168201915b50505050509050919050565b6000600d80546115d390612fc2565b9050116115ef576040518060200160405280600081525061076c565b600d6115fa836123e0565b60405160200161160b9291906132b4565b60405160208183030381529060405292915050565b600c546000906001600160a01b0316331461163a57600080fd5b60115482906001600160401b03161580159061167d5750601154600f546001600160401b039091169061167b9061010090046001600160e01b0316836131a7565b115b1561169b576040516352df9fe560e01b815260040160405180910390fd5b6116a584846124e0565b5050600f5461010090046001600160e01b031692915050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b600b546001600160a01b0316631222cea6336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611742573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611766919061300c565b611783576040516311ebaa2760e11b815260040160405180910390fd5b60115483906001600160401b0316158015906117c65750601154600f546001600160401b03909116906117c49061010090046001600160e01b0316836131a7565b115b156117e4576040516352df9fe560e01b815260040160405180910390fd5b60155460ff161561180857604051631afb0ae560e01b815260040160405180910390fd5b60135442600160201b9091046001600160401b03161180159061183d575060135442600160601b9091046001600160401b0316115b61185a57604051630fe219dd60e21b815260040160405180910390fd5b6011546001600160a01b03868116600160501b909204161461188e576040516282b42960e81b815260040160405180910390fd5b6012546118a990879085906118a39088611e5a565b87611f28565b604080518581526001600160401b03841660208201526001600160a01b038816917f66f7cec2cf267a0c2dec8f68fa7a926f730e7f5be0837f841ea91f9b4c6ced2b910160405180910390a2505050505050565b60155460009060ff161561192457604051631afb0ae560e01b815260040160405180910390fd5b60115482906001600160401b0316158015906119675750601154600f546001600160401b03909116906119659061010090046001600160e01b0316836131a7565b115b15611985576040516352df9fe560e01b815260040160405180910390fd5b60135442600160201b9091046001600160401b0316118015906119ba575060135442600160601b9091046001600160401b0316115b6119d757604051630fe219dd60e21b815260040160405180910390fd5b6002600a5403611a295760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610955565b6002600a5560145415611a4e576040516282b42960e81b815260040160405180910390fd5b6012543390600090611a609086611e5a565b90506000611a6d86610d71565b90506000611a7b8383611f1c565b9050611a898434838a611f28565b611a928261200d565b611a9b836120d3565b50611aaa84611116348461217b565b601254600f546040516101009091046001600160e01b0316815288906001600160a01b038716907f5bc97d73357ac0d035d4b9268a69240988a5776b8a4fcced3dbc223960123f409060200160405180910390a45050600f546001600a5561010090046001600160e01b031695945050505050565b600c546001600160a01b03163314611b3657600080fd5b805161083890600e906020840190612a61565b600c546001600160a01b03163314611b6057600080fd5b6001600160a01b038116611b86576040516282b42960e81b815260040160405180910390fd5b600c80546001600160a01b0319166001600160a01b03831617905550565b60155460ff1615611bc857604051631afb0ae560e01b815260040160405180910390fd5b600c546001600160a01b03163314611bdf57600080fd5b601354600160601b90046001600160401b0316421115611c1257604051631060d8c160e11b815260040160405180910390fd5b6015805460ff19166001179055611c263390565b6001600160a01b03167f3cf0fddeb2fbf69861d5f13d66be17516300342ce630d94fb7ea3388c0c27dce42604051610be791815260200190565b60006001600160e01b031982166380ac58cd60e01b1480611c9157506001600160e01b03198216635b5e139f60e01b145b8061076c57506301ffc9a760e01b6001600160e01b031983161461076c565b6000818152600260205260408120546001600160a01b03168061076c57604051637e27328960e01b815260048101849052602401610955565b610c0c838383600161258e565b6000611d056000836000611d31565b90506001600160a01b03811661083857604051637e27328960e01b815260048101839052602401610955565b600080611d3f858585612694565b90506001600160a01b038116611d9c57611d9784600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b611dbf565b846001600160a01b0316816001600160a01b031614611dbf57611dbf818561278d565b6001600160a01b038516611ddb57611dd68461281e565b611dfe565b846001600160a01b0316816001600160a01b031614611dfe57611dfe85856128cd565b949350505050565b61083882826040518060200160405280600081525061291d565b8151611e33906000906020850190612a61565b508051610c0c906001906020840190612a61565b805161083890600d906020840190612a61565b6000611e66828461336e565b9392505050565b600081815b8551811015611f11576000868281518110611e8f57611e8f613145565b60200260200101519050808311611ed1576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250611efe565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b5080611f098161338d565b915050611e72565b509092149392505050565b6000611e6682846131a7565b80600003611f48576040516282b42960e81b815260040160405180910390fd5b81831015611f6c5760405163c5a8df2f60e01b815260048101839052602401610955565b60135463ffffffff1615801590611fb257506013546001600160a01b03851660009081526010602052604090205463ffffffff91821691611fb091908490611f1c16565b115b15611fd057604051631722816d60e01b815260040160405180910390fd5b611fda84826124e0565b6001600160a01b038416600090815260106020526040812080548392906120029084906131a7565b909155505050505050565b600b546040805163c5f956af60e01b815290516000926001600160a01b03169163c5f956af9160048083019260209291908290030181865afa158015612057573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207b919061315b565b90506120878183612187565b604080518381526001600160a01b038316602082015260018183015290517f7d91e6735310f2a10253c2b777a07cdd5bce000456de934af23dfc9e4aea7f879181900360600190a15050565b601154600090600160501b90046001600160a01b031615806120f3575081155b1561210057506000919050565b60115461211d90600160501b90046001600160a01b031683612187565b601154600160501b90046001600160a01b0316336001600160a01b03167fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a8460405161216b91815260200190565b60405180910390a3506001919050565b6000611e6682846133a6565b8015610838576000826001600160a01b031682620334505a116121aa575a6121af565b620334505b6040519091906000818181858888f193505050503d80600081146121ef576040519150601f19603f3d011682016040523d82523d6000602084013e6121f4565b606091505b5050905080610c0c576040516307a4ced160e51b815260040160405180910390fd5b6001600160a01b03821661224857604051630b61174360e31b81526001600160a01b0383166004820152602401610955565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b156123d957604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906122f79088908890879087906004016133bd565b6020604051808303816000875af1925050508015612332575060408051601f3d908101601f1916820190925261232f918101906133fa565b60015b61239b573d808015612360576040519150601f19603f3d011682016040523d82523d6000602084013e612365565b606091505b50805160000361239357604051633250574960e11b81526001600160a01b0385166004820152602401610955565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b146123d757604051633250574960e11b81526001600160a01b0385166004820152602401610955565b505b5050505050565b6060816000036124075750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612431578061241b8161338d565b915061242a9050600a8361342d565b915061240b565b6000816001600160401b0381111561244b5761244b612c78565b6040519080825280601f01601f191660200182016040528015612475576020820181803683370190505b5090505b8415611dfe5761248a6001836133a6565b9150612497600a86613441565b6124a29060306131a7565b60f81b8183815181106124b7576124b7613145565b60200101906001600160f81b031916908160001a9053506124d9600a8661342d565b9450612479565b60005b81811015610c0c576001600f60018282829054906101000a90046001600160e01b03166125109190613455565b825461010092830a6001600160e01b0381810219909216929091160217909155600f54604080514660e01b6001600160e01b0319166020808301919091529390920490921b63ffffffff19166024820152612586925085910160405160208183030381529060405261258190613480565b611e06565b6001016124e3565b80806125a257506001600160a01b03821615155b156126645760006125b284611cb0565b90506001600160a01b038316158015906125de5750826001600160a01b0316816001600160a01b031614155b80156125f157506125ef81846116be565b155b1561261a5760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610955565b81156126625783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b6000828152600260205260408120546001600160a01b03908116908316156126c1576126c1818486612935565b6001600160a01b038116156126ff576126de60008560008061258e565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b0385161561272e576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b600061279883611192565b6000838152600760205260409020549091508082146127eb576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090612830906001906133a6565b6000838152600960205260408120546008805493945090928490811061285857612858613145565b90600052602060002001549050806008838154811061287957612879613145565b60009182526020808320909101929092558281526009909152604080822084905585825281205560088054806128b1576128b16134a4565b6001900381819060005260206000200160009055905550505050565b600060016128da84611192565b6128e491906133a6565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6129278383612999565b610c0c3360008585856122b5565b6129408383836129fe565b610c0c576001600160a01b03831661296e57604051637e27328960e01b815260048101829052602401610955565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610955565b6001600160a01b0382166129c357604051633250574960e11b815260006004820152602401610955565b60006129d183836000611d31565b90506001600160a01b03811615610c0c576040516339e3563760e11b815260006004820152602401610955565b60006001600160a01b03831615801590611dfe5750826001600160a01b0316846001600160a01b03161480612a385750612a3884846116be565b80611dfe5750506000908152600460205260409020546001600160a01b03908116911614919050565b828054612a6d90612fc2565b90600052602060002090601f016020900481019282612a8f5760008555612ad5565b82601f10612aa857805160ff1916838001178555612ad5565b82800160010185558215612ad5579182015b82811115612ad5578251825591602001919060010190612aba565b50612ae1929150612ae5565b5090565b5b80821115612ae15760008155600101612ae6565b6001600160e01b031981168114610d6e57600080fd5b600060208284031215612b2257600080fd5b8135611e6681612afa565b60005b83811015612b48578181015183820152602001612b30565b838111156109b95750506000910152565b60008151808452612b71816020860160208601612b2d565b601f01601f19169290920160200192915050565b602081526000611e666020830184612b59565b600060208284031215612baa57600080fd5b5035919050565b6001600160a01b0381168114610d6e57600080fd5b60008060408385031215612bd957600080fd5b8235612be481612bb1565b946020939093013593505050565b6001600160401b0381168114610d6e57600080fd5b600080600060608486031215612c1c57600080fd5b8335612c2781612bb1565b92506020840135612c3781612bf2565b929592945050506040919091013590565b600080600060608486031215612c5d57600080fd5b8335612c6881612bb1565b92506020840135612c3781612bb1565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b0381118282101715612cb157612cb1612c78565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612cdf57612cdf612c78565b604052919050565b60006001600160401b03821115612d0057612d00612c78565b50601f01601f191660200190565b6000612d21612d1c84612ce7565b612cb7565b9050828152838383011115612d3557600080fd5b828260208301376000602084830101529392505050565b600082601f830112612d5d57600080fd5b611e6683833560208501612d0e565b600060208284031215612d7e57600080fd5b81356001600160401b03811115612d9457600080fd5b611dfe84828501612d4c565b600060208284031215612db257600080fd5b81356001600160401b03811115612dc857600080fd5b8201601f81018413612dd957600080fd5b611dfe84823560208401612d0e565b600080600060408486031215612dfd57600080fd5b8335925060208401356001600160401b0380821115612e1b57600080fd5b818601915086601f830112612e2f57600080fd5b813581811115612e3e57600080fd5b8760208260051b8501011115612e5357600080fd5b6020830194508093505050509250925092565b600060208284031215612e7857600080fd5b8135611e6681612bb1565b8015158114610d6e57600080fd5b60008060408385031215612ea457600080fd5b8235612eaf81612bb1565b91506020830135612ebf81612e83565b809150509250929050565b60008060008060808587031215612ee057600080fd5b8435612eeb81612bb1565b93506020850135612efb81612bb1565b92506040850135915060608501356001600160401b03811115612f1d57600080fd5b612f2987828801612d4c565b91505092959194509250565b60008060408385031215612f4857600080fd5b8235612f5381612bb1565b91506020830135612ebf81612bb1565b600080600080600060a08688031215612f7b57600080fd5b8535612f8681612bb1565b94506020860135612f9681612bb1565b935060408601359250606086013591506080860135612fb481612bf2565b809150509295509295909350565b600181811c90821680612fd657607f821691505b602082108103612ff657634e487b7160e01b600052602260045260246000fd5b50919050565b805161300781612e83565b919050565b60006020828403121561301e57600080fd5b8151611e6681612e83565b600082601f83011261303a57600080fd5b8151613048612d1c82612ce7565b81815284602083860101111561305d57600080fd5b611dfe826020830160208701612b2d565b805161300781612bb1565b60008060008060008060c0878903121561309257600080fd5b86516001600160401b03808211156130a957600080fd5b6130b58a838b01613029565b975060208901519150808211156130cb57600080fd5b6130d78a838b01613029565b965060408901519150808211156130ed57600080fd5b6130f98a838b01613029565b9550606089015191508082111561310f57600080fd5b5061311c89828a01613029565b93505061312b6080880161306e565b915061313960a0880161306e565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561316d57600080fd5b8151611e6681612bb1565b60006020828403121561318a57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600082198211156131ba576131ba613191565b500190565b805161300781612bf2565b805161ffff8116811461300757600080fd5b805163ffffffff8116811461300757600080fd5b6000610120828403121561320357600080fd5b61320b612c8e565b613214836131bf565b8152613222602084016131ca565b60208201526132336040840161306e565b60408201526060830151606082015261324e608084016131dc565b608082015261325f60a084016131bf565b60a082015261327060c084016131bf565b60c082015260e083015160e082015261010061328d818501612ffc565b908201529392505050565b600081516132aa818560208601612b2d565b9290920192915050565b600080845481600182811c9150808316806132d057607f831692505b602080841082036132ef57634e487b7160e01b86526022600452602486fd5b818015613303576001811461331457613341565b60ff19861689528489019650613341565b60008b81526020902060005b868110156133395781548b820152908501908301613320565b505084890196505b5050505050506133656133548286613298565b64173539b7b760d91b815260050190565b95945050505050565b600081600019048311821515161561338857613388613191565b500290565b60006001820161339f5761339f613191565b5060010190565b6000828210156133b8576133b8613191565b500390565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906133f090830184612b59565b9695505050505050565b60006020828403121561340c57600080fd5b8151611e6681612afa565b634e487b7160e01b600052601260045260246000fd5b60008261343c5761343c613417565b500490565b60008261345057613450613417565b500690565b60006001600160e01b0382811684821680830382111561347757613477613191565b01949350505050565b80516020808301519190811015612ff65760001960209190910360031b1b16919050565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220baa39d31c4063907bf3e8c4a54eecb619e082b66c50c683cd96d0e2aa132a62f64736f6c634300080d0033
Deployed Bytecode
0x60806040526004361061020f5760003560e01c806370a0823111610118578063c87b56dd116100a0578063efef39a11161006f578063efef39a1146106ca578063f2c4ce1e146106dd578063f2fde38b146106fd578063f5a0384c1461071d578063ffa1ad741461073257600080fd5b8063c87b56dd1461064a578063e58306f91461066a578063e985e9c51461068a578063ed50d883146106aa57600080fd5b80639123f01e116100e75780639123f01e146105a857806394847d62146105d557806395d89b41146105f5578063a22cb4651461060a578063b88d4fde1461062a57600080fd5b806370a082311461046c578063867589121461048c5780638da5cb5b146104ac57806390aa0b0f146104cc57600080fd5b80632f745c591161019b5780634f6ccce71161016a5780634f6ccce7146103d957806355f804b3146103f9578063616985ed146104195780636352211e1461043957806370970d561461045957600080fd5b80632f745c591461036457806341e96eb11461038457806342842e0e146103995780634ddf47d4146103b957600080fd5b80630e21ea06116101e25780630e21ea06146102c55780630e46c9a6146102e557806318160ddd1461030557806323b872dd146103245780632cde12151461034457600080fd5b806301ffc9a71461021457806306fdde0314610249578063081812fc1461026b578063095ea7b3146102a3575b600080fd5b34801561022057600080fd5b5061023461022f366004612b10565b610747565b60405190151581526020015b60405180910390f35b34801561025557600080fd5b5061025e610772565b6040516102409190612b85565b34801561027757600080fd5b5061028b610286366004612b98565b610804565b6040516001600160a01b039091168152602001610240565b3480156102af57600080fd5b506102c36102be366004612bc6565b61082d565b005b3480156102d157600080fd5b50600b5461028b906001600160a01b031681565b3480156102f157600080fd5b506102c3610300366004612c07565b61083c565b34801561031157600080fd5b506008545b604051908152602001610240565b34801561033057600080fd5b506102c361033f366004612c48565b61092f565b34801561035057600080fd5b506102c361035f366004612c07565b6109bf565b34801561037057600080fd5b5061031661037f366004612bc6565b610aaa565b34801561039057600080fd5b506102c3610b0f565b3480156103a557600080fd5b506102c36103b4366004612c48565b610bf1565b3480156103c557600080fd5b506102346103d4366004612d6c565b610c11565b3480156103e557600080fd5b506103166103f4366004612b98565b610cf5565b34801561040557600080fd5b506102c3610414366004612da0565b610d4e565b34801561042557600080fd5b50610316610434366004612b98565b610d71565b34801561044557600080fd5b5061028b610454366004612b98565b610ee8565b610316610467366004612de8565b610ef3565b34801561047857600080fd5b50610316610487366004612e66565b611192565b34801561049857600080fd5b506102c36104a7366004612b98565b6111da565b3480156104b857600080fd5b50600c5461028b906001600160a01b031681565b3480156104d857600080fd5b5060115460125460135460145460155461053b946001600160401b0380821695600160401b830461ffff1695600160501b9093046001600160a01b031694909363ffffffff841693600160201b8104841693600160601b90910416919060ff1689565b604080516001600160401b039a8b16815261ffff90991660208a01526001600160a01b0390971696880196909652606087019490945263ffffffff9092166080860152851660a08501529390931660c083015260e082019290925290151561010082015261012001610240565b3480156105b457600080fd5b506103166105c3366004612e66565b60106020526000908152604090205481565b3480156105e157600080fd5b506102c36105f0366004612d6c565b611248565b34801561060157600080fd5b5061025e6114dd565b34801561061657600080fd5b506102c3610625366004612e91565b6114ec565b34801561063657600080fd5b506102c3610645366004612eca565b6114f7565b34801561065657600080fd5b5061025e610665366004612b98565b61150f565b34801561067657600080fd5b50610316610685366004612bc6565b611620565b34801561069657600080fd5b506102346106a5366004612f35565b6116be565b3480156106b657600080fd5b506102c36106c5366004612f63565b6116ec565b6103166106d8366004612b98565b6118fd565b3480156106e957600080fd5b506102c36106f8366004612da0565b611b1f565b34801561070957600080fd5b506102c3610718366004612e66565b611b49565b34801561072957600080fd5b506102c3611ba4565b34801561073e57600080fd5b50610316600481565b60006001600160e01b0319821663780e9d6360e01b148061076c575061076c82611c60565b92915050565b60606000805461078190612fc2565b80601f01602080910402602001604051908101604052809291908181526020018280546107ad90612fc2565b80156107fa5780601f106107cf576101008083540402835291602001916107fa565b820191906000526020600020905b8154815290600101906020018083116107dd57829003601f168201915b5050505050905090565b600061080f82611cb0565b506000828152600460205260409020546001600160a01b031661076c565b610838828233611ce9565b5050565b600b546001600160a01b0316631222cea6336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610892573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b6919061300c565b6108d3576040516311ebaa2760e11b815260040160405180910390fd5b6108dc81611cf6565b604080516001600160401b0384168152602081018390526001600160a01b038516917f40b70b451dc629fad6a565da866d93b8c178df2cb218fc32f6af8041165309c191015b60405180910390a2505050565b6001600160a01b03821661095e57604051633250574960e11b8152600060048201526024015b60405180910390fd5b600061096b838333611d31565b9050836001600160a01b0316816001600160a01b0316146109b9576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610955565b50505050565b600b546001600160a01b0316631222cea6336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a39919061300c565b610a56576040516311ebaa2760e11b815260040160405180910390fd5b610a608382611e06565b604080516001600160401b0384168152602081018390526001600160a01b038516917f780140c12a9c67a3a283c7f237e9577318a108e1dfdeb57542a4655c89be38b79101610922565b6000610ab583611192565b8210610ae65760405163295f44f760e21b81526001600160a01b038416600482015260248101839052604401610955565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b60155460ff1615610b3357604051631afb0ae560e01b815260040160405180910390fd5b600c546001600160a01b03163314610b4a57600080fd5b600f54601180546001600160401b03610100909304831667ffffffffffffffff199091161790556013805442909216600160601b0267ffffffffffffffff60601b19909216919091179055610b9c3390565b601154604080516001600160401b0390921682524260208301526001600160a01b0392909216917fc0786675f6128bc0b8e886ad509fa0cc374ec4c3efe21e941920ea683bd1741d91015b60405180910390a2565b610c0c838383604051806020016040528060008152506114f7565b505050565b600f5460009060ff1615610c37576040516282b42960e81b815260040160405180910390fd5b60008060008060008087806020019051810190610c549190613079565b600c80546001600160a01b0384166001600160a01b0319909116179055949a50929850909650945092509050610ca781600b80546001600160a01b039092166001600160a01b0319909216919091179055565b8551610cba90600d906020890190612a61565b508451610cce90600e906020880190612a61565b50610cd98484611e20565b5050600f805460ff191660019081179091559695505050505050565b6000610d0060085490565b8210610d295760405163295f44f760e21b81526000600482015260248101839052604401610955565b60088281548110610d3c57610d3c613145565b90600052602060002001549050919050565b600c546001600160a01b03163314610d6557600080fd5b610d6e81611e47565b50565b600081600003610d8357506000919050565b600b60009054906101000a90046001600160a01b03166001600160a01b031663a89ae4ba6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfa919061315b565b6001600160a01b031663f5d78161610e8984600b60009054906101000a90046001600160a01b03166001600160a01b0316630c1119bb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e839190613178565b90611e5a565b6040518263ffffffff1660e01b8152600401610ea791815260200190565b602060405180830381865afa158015610ec4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076c9190613178565b600061076c82611cb0565b60155460009060ff1615610f1a57604051631afb0ae560e01b815260040160405180910390fd5b60115484906001600160401b031615801590610f5d5750601154600f546001600160401b0390911690610f5b9061010090046001600160e01b0316836131a7565b115b15610f7b576040516352df9fe560e01b815260040160405180910390fd5b60135442600160201b9091046001600160401b031611801590610fb0575060135442600160601b9091046001600160401b0316115b610fcd57604051630fe219dd60e21b815260040160405180910390fd5b6002600a540361101f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610955565b6002600a55600033905061109f858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506014546040516bffffffffffffffffffffffff19606088901b166020820152909250603401905060405160208183030381529060405280519060200120611e6d565b6110bc576040516346cabb7560e01b815260040160405180910390fd5b6012546000906110cc9088611e5a565b905060006110d988610d71565b905060006110e78383611f1c565b90506110f58434838c611f28565b6110fe8261200d565b611107836120d3565b5061111b84611116348461217b565b612187565b601254600f546040516101009091046001600160e01b031681528a906001600160a01b038716907f5bc97d73357ac0d035d4b9268a69240988a5776b8a4fcced3dbc223960123f409060200160405180910390a45050600f546001600a5561010090046001600160e01b0316979650505050505050565b60006001600160a01b0382166111be576040516322718ad960e21b815260006004820152602401610955565b506001600160a01b031660009081526003602052604090205490565b60155460ff16156111fe57604051631afb0ae560e01b815260040160405180910390fd5b600c546001600160a01b0316331461121557600080fd5b601481905560405181907fac0e7be7f0391f6f84d2d6c5c9300942e4d7e7a79629f63f0078050c21300d9e90600090a250565b60155460ff161561126c57604051631afb0ae560e01b815260040160405180910390fd5b600c546001600160a01b0316331461128357600080fd5b601354600160201b90046001600160401b0316158015906112b55750601354600160201b90046001600160401b031642115b156112d357604051630571129f60e51b815260040160405180910390fd5b6000818060200190518101906112e991906131f0565b9050428160a001516001600160401b031611158061132157508060a001516001600160401b03168160c001516001600160401b031611155b8061133457506032816020015161ffff16115b8061134a575060408101516001600160a01b0316155b15611368576040516371dff4bd60e11b815260040160405180910390fd5b604080516101208101825282516001600160401b0390811680835260208086015161ffff16908401819052858501516001600160a01b031694840185905260608087015190850181905260808088015163ffffffff1690860181905260a080890151861690870181905260c0808a015190961695870186905260e0808a01519088018190526000610100909801979097526011805469ffffffffffffffffffff1916909517600160401b909402939093177fffff0000000000000000000000000000000000000000ffffffffffffffffffff16600160501b90970296909617909255601291909155601380546bffffffffffffffffffffffff1916909417600160201b9091021767ffffffffffffffff60601b1916600160601b909102179091556014556015805460ff19169055336001600160a01b03167f7f5a7a2bf5c04c7c8759c017a2991abaf03db78e2595e806fe7b6add4dffe4b6426040516114d191815260200190565b60405180910390a25050565b60606001805461078190612fc2565b610838338383612216565b61150284848461092f565b6109b933858585856122b5565b606061151a82611cb0565b506000600e805461152a90612fc2565b905011156115c457600e805461153f90612fc2565b80601f016020809104026020016040519081016040528092919081815260200182805461156b90612fc2565b80156115b85780601f1061158d576101008083540402835291602001916115b8565b820191906000526020600020905b81548152906001019060200180831161159b57829003601f168201915b50505050509050919050565b6000600d80546115d390612fc2565b9050116115ef576040518060200160405280600081525061076c565b600d6115fa836123e0565b60405160200161160b9291906132b4565b60405160208183030381529060405292915050565b600c546000906001600160a01b0316331461163a57600080fd5b60115482906001600160401b03161580159061167d5750601154600f546001600160401b039091169061167b9061010090046001600160e01b0316836131a7565b115b1561169b576040516352df9fe560e01b815260040160405180910390fd5b6116a584846124e0565b5050600f5461010090046001600160e01b031692915050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b600b546001600160a01b0316631222cea6336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611742573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611766919061300c565b611783576040516311ebaa2760e11b815260040160405180910390fd5b60115483906001600160401b0316158015906117c65750601154600f546001600160401b03909116906117c49061010090046001600160e01b0316836131a7565b115b156117e4576040516352df9fe560e01b815260040160405180910390fd5b60155460ff161561180857604051631afb0ae560e01b815260040160405180910390fd5b60135442600160201b9091046001600160401b03161180159061183d575060135442600160601b9091046001600160401b0316115b61185a57604051630fe219dd60e21b815260040160405180910390fd5b6011546001600160a01b03868116600160501b909204161461188e576040516282b42960e81b815260040160405180910390fd5b6012546118a990879085906118a39088611e5a565b87611f28565b604080518581526001600160401b03841660208201526001600160a01b038816917f66f7cec2cf267a0c2dec8f68fa7a926f730e7f5be0837f841ea91f9b4c6ced2b910160405180910390a2505050505050565b60155460009060ff161561192457604051631afb0ae560e01b815260040160405180910390fd5b60115482906001600160401b0316158015906119675750601154600f546001600160401b03909116906119659061010090046001600160e01b0316836131a7565b115b15611985576040516352df9fe560e01b815260040160405180910390fd5b60135442600160201b9091046001600160401b0316118015906119ba575060135442600160601b9091046001600160401b0316115b6119d757604051630fe219dd60e21b815260040160405180910390fd5b6002600a5403611a295760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610955565b6002600a5560145415611a4e576040516282b42960e81b815260040160405180910390fd5b6012543390600090611a609086611e5a565b90506000611a6d86610d71565b90506000611a7b8383611f1c565b9050611a898434838a611f28565b611a928261200d565b611a9b836120d3565b50611aaa84611116348461217b565b601254600f546040516101009091046001600160e01b0316815288906001600160a01b038716907f5bc97d73357ac0d035d4b9268a69240988a5776b8a4fcced3dbc223960123f409060200160405180910390a45050600f546001600a5561010090046001600160e01b031695945050505050565b600c546001600160a01b03163314611b3657600080fd5b805161083890600e906020840190612a61565b600c546001600160a01b03163314611b6057600080fd5b6001600160a01b038116611b86576040516282b42960e81b815260040160405180910390fd5b600c80546001600160a01b0319166001600160a01b03831617905550565b60155460ff1615611bc857604051631afb0ae560e01b815260040160405180910390fd5b600c546001600160a01b03163314611bdf57600080fd5b601354600160601b90046001600160401b0316421115611c1257604051631060d8c160e11b815260040160405180910390fd5b6015805460ff19166001179055611c263390565b6001600160a01b03167f3cf0fddeb2fbf69861d5f13d66be17516300342ce630d94fb7ea3388c0c27dce42604051610be791815260200190565b60006001600160e01b031982166380ac58cd60e01b1480611c9157506001600160e01b03198216635b5e139f60e01b145b8061076c57506301ffc9a760e01b6001600160e01b031983161461076c565b6000818152600260205260408120546001600160a01b03168061076c57604051637e27328960e01b815260048101849052602401610955565b610c0c838383600161258e565b6000611d056000836000611d31565b90506001600160a01b03811661083857604051637e27328960e01b815260048101839052602401610955565b600080611d3f858585612694565b90506001600160a01b038116611d9c57611d9784600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b611dbf565b846001600160a01b0316816001600160a01b031614611dbf57611dbf818561278d565b6001600160a01b038516611ddb57611dd68461281e565b611dfe565b846001600160a01b0316816001600160a01b031614611dfe57611dfe85856128cd565b949350505050565b61083882826040518060200160405280600081525061291d565b8151611e33906000906020850190612a61565b508051610c0c906001906020840190612a61565b805161083890600d906020840190612a61565b6000611e66828461336e565b9392505050565b600081815b8551811015611f11576000868281518110611e8f57611e8f613145565b60200260200101519050808311611ed1576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250611efe565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b5080611f098161338d565b915050611e72565b509092149392505050565b6000611e6682846131a7565b80600003611f48576040516282b42960e81b815260040160405180910390fd5b81831015611f6c5760405163c5a8df2f60e01b815260048101839052602401610955565b60135463ffffffff1615801590611fb257506013546001600160a01b03851660009081526010602052604090205463ffffffff91821691611fb091908490611f1c16565b115b15611fd057604051631722816d60e01b815260040160405180910390fd5b611fda84826124e0565b6001600160a01b038416600090815260106020526040812080548392906120029084906131a7565b909155505050505050565b600b546040805163c5f956af60e01b815290516000926001600160a01b03169163c5f956af9160048083019260209291908290030181865afa158015612057573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207b919061315b565b90506120878183612187565b604080518381526001600160a01b038316602082015260018183015290517f7d91e6735310f2a10253c2b777a07cdd5bce000456de934af23dfc9e4aea7f879181900360600190a15050565b601154600090600160501b90046001600160a01b031615806120f3575081155b1561210057506000919050565b60115461211d90600160501b90046001600160a01b031683612187565b601154600160501b90046001600160a01b0316336001600160a01b03167fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a8460405161216b91815260200190565b60405180910390a3506001919050565b6000611e6682846133a6565b8015610838576000826001600160a01b031682620334505a116121aa575a6121af565b620334505b6040519091906000818181858888f193505050503d80600081146121ef576040519150601f19603f3d011682016040523d82523d6000602084013e6121f4565b606091505b5050905080610c0c576040516307a4ced160e51b815260040160405180910390fd5b6001600160a01b03821661224857604051630b61174360e31b81526001600160a01b0383166004820152602401610955565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b156123d957604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906122f79088908890879087906004016133bd565b6020604051808303816000875af1925050508015612332575060408051601f3d908101601f1916820190925261232f918101906133fa565b60015b61239b573d808015612360576040519150601f19603f3d011682016040523d82523d6000602084013e612365565b606091505b50805160000361239357604051633250574960e11b81526001600160a01b0385166004820152602401610955565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b146123d757604051633250574960e11b81526001600160a01b0385166004820152602401610955565b505b5050505050565b6060816000036124075750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612431578061241b8161338d565b915061242a9050600a8361342d565b915061240b565b6000816001600160401b0381111561244b5761244b612c78565b6040519080825280601f01601f191660200182016040528015612475576020820181803683370190505b5090505b8415611dfe5761248a6001836133a6565b9150612497600a86613441565b6124a29060306131a7565b60f81b8183815181106124b7576124b7613145565b60200101906001600160f81b031916908160001a9053506124d9600a8661342d565b9450612479565b60005b81811015610c0c576001600f60018282829054906101000a90046001600160e01b03166125109190613455565b825461010092830a6001600160e01b0381810219909216929091160217909155600f54604080514660e01b6001600160e01b0319166020808301919091529390920490921b63ffffffff19166024820152612586925085910160405160208183030381529060405261258190613480565b611e06565b6001016124e3565b80806125a257506001600160a01b03821615155b156126645760006125b284611cb0565b90506001600160a01b038316158015906125de5750826001600160a01b0316816001600160a01b031614155b80156125f157506125ef81846116be565b155b1561261a5760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610955565b81156126625783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b6000828152600260205260408120546001600160a01b03908116908316156126c1576126c1818486612935565b6001600160a01b038116156126ff576126de60008560008061258e565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b0385161561272e576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b600061279883611192565b6000838152600760205260409020549091508082146127eb576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090612830906001906133a6565b6000838152600960205260408120546008805493945090928490811061285857612858613145565b90600052602060002001549050806008838154811061287957612879613145565b60009182526020808320909101929092558281526009909152604080822084905585825281205560088054806128b1576128b16134a4565b6001900381819060005260206000200160009055905550505050565b600060016128da84611192565b6128e491906133a6565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6129278383612999565b610c0c3360008585856122b5565b6129408383836129fe565b610c0c576001600160a01b03831661296e57604051637e27328960e01b815260048101829052602401610955565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610955565b6001600160a01b0382166129c357604051633250574960e11b815260006004820152602401610955565b60006129d183836000611d31565b90506001600160a01b03811615610c0c576040516339e3563760e11b815260006004820152602401610955565b60006001600160a01b03831615801590611dfe5750826001600160a01b0316846001600160a01b03161480612a385750612a3884846116be565b80611dfe5750506000908152600460205260409020546001600160a01b03908116911614919050565b828054612a6d90612fc2565b90600052602060002090601f016020900481019282612a8f5760008555612ad5565b82601f10612aa857805160ff1916838001178555612ad5565b82800160010185558215612ad5579182015b82811115612ad5578251825591602001919060010190612aba565b50612ae1929150612ae5565b5090565b5b80821115612ae15760008155600101612ae6565b6001600160e01b031981168114610d6e57600080fd5b600060208284031215612b2257600080fd5b8135611e6681612afa565b60005b83811015612b48578181015183820152602001612b30565b838111156109b95750506000910152565b60008151808452612b71816020860160208601612b2d565b601f01601f19169290920160200192915050565b602081526000611e666020830184612b59565b600060208284031215612baa57600080fd5b5035919050565b6001600160a01b0381168114610d6e57600080fd5b60008060408385031215612bd957600080fd5b8235612be481612bb1565b946020939093013593505050565b6001600160401b0381168114610d6e57600080fd5b600080600060608486031215612c1c57600080fd5b8335612c2781612bb1565b92506020840135612c3781612bf2565b929592945050506040919091013590565b600080600060608486031215612c5d57600080fd5b8335612c6881612bb1565b92506020840135612c3781612bb1565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b0381118282101715612cb157612cb1612c78565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612cdf57612cdf612c78565b604052919050565b60006001600160401b03821115612d0057612d00612c78565b50601f01601f191660200190565b6000612d21612d1c84612ce7565b612cb7565b9050828152838383011115612d3557600080fd5b828260208301376000602084830101529392505050565b600082601f830112612d5d57600080fd5b611e6683833560208501612d0e565b600060208284031215612d7e57600080fd5b81356001600160401b03811115612d9457600080fd5b611dfe84828501612d4c565b600060208284031215612db257600080fd5b81356001600160401b03811115612dc857600080fd5b8201601f81018413612dd957600080fd5b611dfe84823560208401612d0e565b600080600060408486031215612dfd57600080fd5b8335925060208401356001600160401b0380821115612e1b57600080fd5b818601915086601f830112612e2f57600080fd5b813581811115612e3e57600080fd5b8760208260051b8501011115612e5357600080fd5b6020830194508093505050509250925092565b600060208284031215612e7857600080fd5b8135611e6681612bb1565b8015158114610d6e57600080fd5b60008060408385031215612ea457600080fd5b8235612eaf81612bb1565b91506020830135612ebf81612e83565b809150509250929050565b60008060008060808587031215612ee057600080fd5b8435612eeb81612bb1565b93506020850135612efb81612bb1565b92506040850135915060608501356001600160401b03811115612f1d57600080fd5b612f2987828801612d4c565b91505092959194509250565b60008060408385031215612f4857600080fd5b8235612f5381612bb1565b91506020830135612ebf81612bb1565b600080600080600060a08688031215612f7b57600080fd5b8535612f8681612bb1565b94506020860135612f9681612bb1565b935060408601359250606086013591506080860135612fb481612bf2565b809150509295509295909350565b600181811c90821680612fd657607f821691505b602082108103612ff657634e487b7160e01b600052602260045260246000fd5b50919050565b805161300781612e83565b919050565b60006020828403121561301e57600080fd5b8151611e6681612e83565b600082601f83011261303a57600080fd5b8151613048612d1c82612ce7565b81815284602083860101111561305d57600080fd5b611dfe826020830160208701612b2d565b805161300781612bb1565b60008060008060008060c0878903121561309257600080fd5b86516001600160401b03808211156130a957600080fd5b6130b58a838b01613029565b975060208901519150808211156130cb57600080fd5b6130d78a838b01613029565b965060408901519150808211156130ed57600080fd5b6130f98a838b01613029565b9550606089015191508082111561310f57600080fd5b5061311c89828a01613029565b93505061312b6080880161306e565b915061313960a0880161306e565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561316d57600080fd5b8151611e6681612bb1565b60006020828403121561318a57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600082198211156131ba576131ba613191565b500190565b805161300781612bf2565b805161ffff8116811461300757600080fd5b805163ffffffff8116811461300757600080fd5b6000610120828403121561320357600080fd5b61320b612c8e565b613214836131bf565b8152613222602084016131ca565b60208201526132336040840161306e565b60408201526060830151606082015261324e608084016131dc565b608082015261325f60a084016131bf565b60a082015261327060c084016131bf565b60c082015260e083015160e082015261010061328d818501612ffc565b908201529392505050565b600081516132aa818560208601612b2d565b9290920192915050565b600080845481600182811c9150808316806132d057607f831692505b602080841082036132ef57634e487b7160e01b86526022600452602486fd5b818015613303576001811461331457613341565b60ff19861689528489019650613341565b60008b81526020902060005b868110156133395781548b820152908501908301613320565b505084890196505b5050505050506133656133548286613298565b64173539b7b760d91b815260050190565b95945050505050565b600081600019048311821515161561338857613388613191565b500290565b60006001820161339f5761339f613191565b5060010190565b6000828210156133b8576133b8613191565b500390565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906133f090830184612b59565b9695505050505050565b60006020828403121561340c57600080fd5b8151611e6681612afa565b634e487b7160e01b600052601260045260246000fd5b60008261343c5761343c613417565b500490565b60008261345057613450613417565b500690565b60006001600160e01b0382811684821680830382111561347757613477613191565b01949350505050565b80516020808301519190811015612ff65760001960209190910360031b1b16919050565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220baa39d31c4063907bf3e8c4a54eecb619e082b66c50c683cd96d0e2aa132a62f64736f6c634300080d0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.