Source Code
Latest 25 from a total of 29 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Delete Order | 24246293 | 62 days ago | IN | 0 ETH | 0.000127 | ||||
| Create Offer | 21953519 | 383 days ago | IN | 1 ETH | 0.00016691 | ||||
| Fill Order | 21924037 | 387 days ago | IN | 0.01 ETH | 0.00056387 | ||||
| Set Market Fees | 21795053 | 405 days ago | IN | 0 ETH | 0.00011084 | ||||
| Update Order Pri... | 21753514 | 411 days ago | IN | 0 ETH | 0.00008804 | ||||
| Update Order Pri... | 21692075 | 419 days ago | IN | 0 ETH | 0.0001472 | ||||
| Delete Order | 21664900 | 423 days ago | IN | 0 ETH | 0.00263474 | ||||
| Fill Order | 21615524 | 430 days ago | IN | 0.01 ETH | 0.00349808 | ||||
| Create Offer | 21372757 | 464 days ago | IN | 1 ETH | 0.00814646 | ||||
| Create Offer | 21331809 | 470 days ago | IN | 1 ETH | 0.00467102 | ||||
| Fill Order | 21291622 | 475 days ago | IN | 0.01 ETH | 0.00144222 | ||||
| Fill Order | 21288791 | 476 days ago | IN | 0.01 ETH | 0.00155882 | ||||
| Fill Order | 21288405 | 476 days ago | IN | 0.01 ETH | 0.00233678 | ||||
| Fill Order | 21266590 | 479 days ago | IN | 0.01 ETH | 0.00228175 | ||||
| Fill Order | 21266379 | 479 days ago | IN | 0.01 ETH | 0.0029743 | ||||
| Create Offer | 21241481 | 482 days ago | IN | 0.69 ETH | 0.00118085 | ||||
| Create Offer | 21193108 | 489 days ago | IN | 0.12 ETH | 0.00216232 | ||||
| Delete Order | 20971844 | 520 days ago | IN | 0 ETH | 0.00218184 | ||||
| Delete Order | 20964905 | 521 days ago | IN | 0 ETH | 0.00217394 | ||||
| Delete Order | 20964897 | 521 days ago | IN | 0 ETH | 0.00221841 | ||||
| Create Offer | 20805946 | 543 days ago | IN | 0.15 ETH | 0.00212859 | ||||
| Delete Order | 20550086 | 579 days ago | IN | 0 ETH | 0.00013285 | ||||
| Delete Offer | 20507060 | 585 days ago | IN | 0 ETH | 0.00007114 | ||||
| Create Offer | 20501051 | 585 days ago | IN | 0.25 ETH | 0.00022563 | ||||
| Create Offer | 20500148 | 586 days ago | IN | 0.2 ETH | 0.00024038 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Transfer | 21953750 | 383 days ago | 0.8 ETH | ||||
| Transfer | 21953750 | 383 days ago | 0.1 ETH | ||||
| Transfer | 21953750 | 383 days ago | 0.1 ETH | ||||
| Transfer | 21924037 | 387 days ago | 0.009 ETH | ||||
| Transfer | 21924037 | 387 days ago | 0.001 ETH | ||||
| Transfer | 21615524 | 430 days ago | 0.0085 ETH | ||||
| Transfer | 21615524 | 430 days ago | 0.001 ETH | ||||
| Transfer | 21615524 | 430 days ago | 0.0005 ETH | ||||
| Transfer | 21372981 | 464 days ago | 0.8 ETH | ||||
| Transfer | 21372981 | 464 days ago | 0.05 ETH | ||||
| Transfer | 21372981 | 464 days ago | 0.1 ETH | ||||
| Transfer | 21372981 | 464 days ago | 0.05 ETH | ||||
| Transfer | 21331851 | 470 days ago | 0.85 ETH | ||||
| Transfer | 21331851 | 470 days ago | 0.1 ETH | ||||
| Transfer | 21331851 | 470 days ago | 0.05 ETH | ||||
| Transfer | 21291622 | 475 days ago | 0.0085 ETH | ||||
| Transfer | 21291622 | 475 days ago | 0.001 ETH | ||||
| Transfer | 21291622 | 475 days ago | 0.0005 ETH | ||||
| Transfer | 21288791 | 476 days ago | 0.0085 ETH | ||||
| Transfer | 21288791 | 476 days ago | 0.001 ETH | ||||
| Transfer | 21288791 | 476 days ago | 0.0005 ETH | ||||
| Transfer | 21288405 | 476 days ago | 0.0085 ETH | ||||
| Transfer | 21288405 | 476 days ago | 0.001 ETH | ||||
| Transfer | 21288405 | 476 days ago | 0.0005 ETH | ||||
| Transfer | 21266590 | 479 days ago | 0.0085 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
NinfaMarketplace
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 4194304 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
/*----------------------------------------------------------*|
|* ███ ██ ██ ███ ██ ███████ █████ *|
|* ████ ██ ██ ████ ██ ██ ██ ██ *|
|* ██ ██ ██ ██ ██ ██ ██ █████ ███████ *|
|* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ *|
|* ██ ████ ██ ██ ████ ██ ██ ██ *|
|*----------------------------------------------------------*/
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import "./utils/Counters.sol";
import "./utils/RoyaltyEngineV1.sol";
import "./access/Ownable.sol";
/**
*
* @title NinfaMarketplace *
* *
* @notice On-chain NFT marketplace *
* *
* @custom:security-contact tech@ninfa.io *
*
*/
contract NinfaMarketplace is Ownable, RoyaltyEngineV1 {
/*----------------------------------------------------------*|
|* # VARIABLES *|
|*----------------------------------------------------------*/
using Counters for Counters.Counter;
/// @notice Orders counter
Counters.Counter private _orderCount;
/// @notice Offers counter
Counters.Counter private _offerCount;
/// @notice address of admin multisig contract for receiving fees generated
/// by the marketplace
address private _feeRecipient;
/// @notice Ninfa's external registry, mapping Ninfa's ERC721 sovreign
/// collection's tokenIds to a boolean value
/// indicating if the token has been sold on any of Ninfa's contracts, such
/// as this marketplace or an auction
/// contract.
address private immutable _PRIMARY_MARKET_REGISTRY;
///@notice constant 10,000 BPS = 100% shares sale price
uint256 private constant _BPS_DENOMINATOR = 10_000;
/// @notice Ninfa Marketplace fee percentage on primary sales from orders,
/// expressed in basis points
uint256 private _primaryOrdersFee;
/// @notice Ninfa Marketplace fee percentage on primary sales from offers,
/// expressed in basis points
uint256 private _primaryOffersFee;
/// @notice Ninfa Marketplace fee percentage on all secondary sales,
/// expressed in basis points
uint256 private _secondaryMarketFee;
/// @notice codehash of Ninfa's ERC721 sovreign collection
bytes32 private _ERC721SovreignV1CodeHash;
/// @notice `_orderCount` counter to `_Order` struct mapping
mapping(uint256 => _Order) private _orders;
/// @notice `_offerCount` counter to `_Offer` struct mapping
mapping(uint256 => _Offer) public offers;
/*----------------------------------------------------------*|
|* # STRUCTS *|
|*----------------------------------------------------------*/
/**
* @dev the `Order` struct is used both for storing order information, as
* well as trade information when passed as a
* function parameter to the private `_trade` function
* @param tokenId the NFT id, for now we only allow trading NINFA NFT's so
* no erc721 address is needed
* @param unitPrice ERC-1155 unit price in ETH, or total price if ERC-721
* since there is only 1 unit of each token.
* @dev when the `Order` struct is passed as a function parameter to
* `_trade`, `unitPrice` always refers to the
* total price of ERC-1155 tokens, i.e. token value * unit price
* @param collection address of the ERC721 or ERC1155 contract. Doesn't
* require any access control besides the
* @param erc1155Value the NFT amount, _amount == 0 for ERC721 and _amount >
* 0 for ERC1155
* @param commissionBps commission amounts, expressed in basis points 0 -
* 10000
* @param commissionReceivers receivers of commission on sales (primary AND
* secondary)
* @param collection address of the collection being sold
* @param from always refers to the seller, who either creater an order or
* is accepting an offer.
* @param operator address of an authorized operator, such as a gallery
* managing an artist; the operator is allowed
* to change or cancel an order they created on the Marketplace.
* @dev operator address usually also corresponds to the commission receiver
* in order to receive sale commissions,
* unless `commissionReceiver` is set to yet another address, e.g. a payment
* splitter.
*/
struct _Order {
uint256 tokenId;
uint256 unitPrice;
uint256 erc1155Value;
address collection;
address from;
address operator;
uint256[] commissionBps;
address[] commissionReceivers;
}
struct _Offer {
uint256 tokenId;
uint256 unitPrice;
uint256 erc1155Value;
address collection;
address from; // buyer
}
/*----------------------------------------------------------*|
|* # EVENTS *|
|*----------------------------------------------------------*/
event OrderCreated(uint256 orderId);
event OrderUpdated(uint256 orderId);
event OrderDeleted(uint256 orderId);
event OfferCreated(uint256 offerId);
event OfferUpdated(uint256 offerId);
event OfferDeleted(uint256 offerId);
// we have order/offer id and all the related data stored in db.
event Trade( // seller
address indexed collection,
uint256 indexed tokenId,
address indexed from,
uint256 id,
uint256 price,
uint256 erc1155Value
);
/*----------------------------------------------------------*|
|* # ORDERS *|
|*----------------------------------------------------------*/
/**
* @notice create a new order on the marketplace by transfering an NFT to
* it.
* @dev Will create a new order by sending tokens with data bytes containing
* function parameters
*
* Require:
*
* - can only be called by an NFT smart contract transfering an NFT to the
* marketplace
*
*/
function _createOrder(
address _operator, // either the previous owner or operator, i.e.
// whichever address called safeTransferFrom on
// the ERC1155 contract
address _from, // previous owner, i.e. seller
uint256 _id,
uint256 _value,
uint256 _unitPrice,
uint256[] memory _commissionBps,
address[] memory _commissionReceivers
)
private
{
// `_orderCount` starts at 1
_orderCount.increment();
uint256 _orderId = _orderCount.current();
// create order with new `_orderId` in orders mapping
_orders[_orderId] = _Order(
_id,
_unitPrice,
_value,
msg.sender, // collection
_from,
_operator,
_commissionBps,
_commissionReceivers
);
emit OrderCreated(_orderId);
}
/// @dev only for 1155 for updating the price and LOWER the amount
function updateOrder(uint256 _erc1155RedeemAmount, uint256 _unitPrice, uint256 _orderId) external {
lowerOrderErc1155Amount(_orderId, _erc1155RedeemAmount);
_orders[_orderId].unitPrice = _unitPrice;
}
/**
* @notice cancels order and transfers NFT back to owner
* @param _orderId the Id of the order
* @dev delete `_orders[_orderId]` from storage BEFORE making external calls
* for transfering the NFT back to the
* seller (check-effects pattern)
*
*
* SHOULD:
*
* This function does not check whether the order exists or not
*
*/
function deleteOrder(uint256 _orderId) external {
_Order memory order = _orders[_orderId];
require(msg.sender == order.operator);
delete _orders[_orderId];
_transferNFT(order.collection, address(this), msg.sender, order.tokenId, order.erc1155Value);
emit OrderDeleted(_orderId);
}
/**
* @param _unitPrice will override the old price, note that it may be 0
* although this could only mean that a mistake
* was made
* @dev this function doesn't enforce a positive value for `_unitPrice` in
* order to save a little gas for the users.
* @dev if `_unitPrice` is set to 0, the order will be deleted from the
* database (not from the smart contract), see
* {NinfaMarketplace-OrderUpdated} modifier
*/
function updateOrderPrice(uint256 _orderId, uint256 _unitPrice) external {
_Order storage order = _orders[_orderId];
require(msg.sender == order.operator);
order.unitPrice = _unitPrice;
emit OrderUpdated(_orderId);
}
/**
* @notice function to lower an order's amount of the ERC-1155 tokenId on
* sale, doesn't apply to ERC-721 because it
* is non-fungible
* @param _erc1155RedeemAmount is the (negative) difference of tokens to be
* withdrawn by the seller. Should be
* different from 0, although not strictly required.
*/
function lowerOrderErc1155Amount(uint256 _orderId, uint256 _erc1155RedeemAmount) public {
_Order storage order = _orders[_orderId];
require(msg.sender == order.operator);
/// @dev warning, make changes to storage BEFORE making external calls
/// for transfering the NFT back to the
/// seller (check-effects-interactions pattern)
order.erc1155Value -= _erc1155RedeemAmount;
(bool success,) = order.collection.call(
abi.encodeWithSelector(
0xf242432a, // bytes4(keccak256('safeTransferFrom(address,address,uint256,uint256,bytes)'))
address(this),
msg.sender,
order.tokenId,
_erc1155RedeemAmount,
""
)
);
require(success);
if (order.erc1155Value == 0) {
delete _orders[_orderId]; // it is not possible to delete using
// storage pointers
// https://docs.soliditylang.org/en/develop/types.html#data-location
emit OrderDeleted(_orderId);
} else {
emit OrderUpdated(_orderId);
}
}
function setOrderCommission(
uint256 _orderId,
uint256[] memory _commissionBps,
address[] memory _commissionReceivers) external {
// should we check if the total commission is less than 10000?
// should revert in trade function anyway
require(msg.sender == _orders[_orderId].operator);
_orders[_orderId].commissionBps = _commissionBps;
_orders[_orderId].commissionReceivers = _commissionReceivers;
emit OrderUpdated(_orderId);
}
/*----------------------------------------------------------*|
|* # OFFERS *|
|*----------------------------------------------------------*/
/**
* @dev offers can be made independently of whether the token is on sale or
* not, the msg.value is used to determine
* the offer amount, so no function parameter is needed for that
* @dev there is no require to check that an offer or offer doesn't already
* exist and if so, that the offer amount
* is not greater than the order itself, this was omitted in order to save
* gas; the frontend should check this in
* order to prevent mistakes from the user
* @param _collection address of the erc721 implementation contract or proxy
* contract
* @param _tokenId the token Id to make an offer to
* @param _amount the NFT amount, _amount == 0 for ERC721 and _amount > 0
* for ERC1155
* @param _from needed in order to integrate Wert payment solution, because
* in every txn Wert is the `msg.sender`.
* using _msgSender does not represent a security risk, on the other
* hand, it is possible for the buyer to use
* this parameter simply in order to transfer the NFT to an address other
* than their own, this can be useful for
* external contract buying NFTs.
*/
function createOffer(
address _collection,
uint256 _tokenId,
uint256 _amount,
address _from,
uint256 _unitPrice
)
external
payable
{
_offerCount.increment(); // start count at 1
if (_amount == 0) require(msg.value == _unitPrice);
else require(msg.value == _unitPrice * _amount);
offers[_offerCount.current()] = _Offer(
_tokenId, // uint256 tokenId;
_unitPrice, // uint256 unitPrice;
_amount, // uint256 amount;
_collection, // address collection;
_from // address from;
);
emit OfferCreated(_offerCount.current());
}
/**
* @dev cancels offer and refunds ETH back to bidder. When an order gets
* filled, the offer isn't marked as
* cancelled, in order to allow users to claim back their money.
* @param _offerId the Id of the offer.
*/
function deleteOffer(uint256 _offerId) external {
// in memory copy needed so that it is possible to delete the struct
// inside the storage offers mapping, while
// keeping check effects interact pattern intact
_Offer memory offer = offers[_offerId];
uint256 refund;
if (offer.erc1155Value == 0) {
refund = offer.unitPrice;
} else {
refund = offer.unitPrice * offer.erc1155Value;
}
require(msg.sender == offer.from);
// mark offer as cancelled forever, updating offer price before external
// call, Checks Effects Interactions
// pattern
delete offers[_offerId];
// transfer the offer amount back to bidder
_sendValue(offer.from, refund);
emit OfferDeleted(_offerId);
}
/**
* @dev this is one of two functions called by a buyer in order to modify
* their offer, there are two functions,
* `raiseOffer()` and `lowerOffer()`, because they expect different
* parameters depending on whether the offer is
* being raised or lowerd.
* A `msg.value` is required, this function will add the amount sent to
* the old offer amount. The frontend
* needs to calculate the difference between the old and new offer.
* E.g. A buyer calls createOffer() and pays 0.1 ETH. The same buyer
* later wants to raise the offer to 0.3 ETH,
* therefore they now need to send 0.2 ETH, because 0.1 was was sent before.
* @dev anyone can call this function, i.e. requiring that caller is offer
* creator is not needed
* @param _offerId the id of the offer
* call this function only if the new total price is greater than the old
* total price
*/
function raiseOfferPrice(uint256 _offerId, uint256 _erc1155Value, uint256 _unitPrice) external payable {
_Offer storage _offer = offers[_offerId];
require(msg.sender == _offer.from);
if (_offer.erc1155Value == 0) {
require(msg.value == _unitPrice - _offer.unitPrice);
} else {
require(msg.value == (_unitPrice * _erc1155Value) - (_offer.unitPrice * _offer.erc1155Value));
}
_offer.unitPrice = _unitPrice; // transfer extra amount needed on top of
// older offer
_offer.erc1155Value = _erc1155Value;
emit OfferUpdated(_offerId);
}
/**
* @dev this is one of two functions called by a buyer in order to modify
* their offer, there are two functions,
* `raiseOffer()` and `lowerOffer()`, because they expect different
* parameters depending on whether the offer is
* being raised or lowerd.
* In contrast with `raiseOffer()`, instead of `msg.value` this
* function expects a uint parameter representing
* the new (lower) offer; the buyer will get refunded the difference.
* E.g. A buyer calls createOffer() and pays 0.3 ETH. The same buyer
* later wants to lower the offer to 0.1 ETH,
* therefore they will get refunded 0.2 ETH. I.e. The amount expected by the
* `_newAmount` paramer is 0.1 ETH (1^17).
* @param _offerId the id of the offer
*/
function lowerOfferPrice(uint256 _offerId, uint256 _erc1155Amount, uint256 _unitPrice) external {
_Offer storage _offer = offers[_offerId];
require(msg.sender == _offer.from, "hwy");
uint256 refund;
if (_erc1155Amount == 0) {
refund = _offer.unitPrice - _unitPrice;
} else {
refund = (_offer.unitPrice * _offer.erc1155Value) - (_unitPrice * _erc1155Amount);
_offer.erc1155Value = _erc1155Amount;
}
_offer.unitPrice = _unitPrice; // needed to store result before offer
// price is updated
// transfer the difference between old and new lower offer to the user
_sendValue(msg.sender, refund);
emit OfferUpdated(_offerId);
}
function acceptListedTokenOffer(
uint256 _orderId,
uint256 _offerId,
uint256[] memory _commissionBps,
address[] memory _commissionReceivers
)
external
{
_Order memory order = _orders[_orderId];
_Offer memory offer = offers[_offerId];
require(order.operator == msg.sender && order.tokenId == offer.tokenId && order.collection == offer.collection);
delete _orders[_orderId];
delete offers[_offerId];
_trade(
_Order(
order.tokenId, // uint256 tokenId
offer.unitPrice, // offer price, not order price
0,
order.collection, // address collection
msg.sender, // seller
offer.from, // buyer / nft recipient
_commissionBps, // uint256 commissionBps
_commissionReceivers
),
_orderId,
_primaryOffersFee
);
}
/*----------------------------------------------------------*|
|* # TRADING *|
|*----------------------------------------------------------*/
/**
* @notice the collector calls this function to buy an NFT at the ask price,
* only if an order exists
* @notice if someone has an open offer but calls fillOrder, the offer will
* remain open, meaning they will need to
* call cancelOffer() to get a refund. This is unlikely, as users will
* likely be aware of this and use the refund in
* order to pay for part of the order.
* @param _id avoids having to store a mapping to order id like the
* deprecated `mapping(address => mapping(uint256
* => uint256)) private _tokenToOrderId` which would have not worked for
* erc1155 as each token has a supply.
* _orderId does not constitute a vulnerability as it is user provided,
* since A) a regular user will go through the
* frontend which gets orderId from events
* @param _buyer needed in order to integrate Wert payment solution, because
* in every txn Wert is the msg.sender,
* although using msg.sender would cost less gas.
* using _msgSender does not represent a security risk, on the other hand,
* it is possible for the buyer to use this
* parameter simply in order to transfer the NFT to an address other than
* their own, this can be useful for external
* contract buying NFTs.
* + @param _erc1155Value market order amount (total or partial fill).
* `_erc1155Value == 0` corresponds to one erc721 tokenId, `_erc1155Value >
* 0` for erc1155 tokenIds
*
* MUST:
*
* - `msg.value` must be equal to `_orders[_orderId]der.unitPrice *
* buyAmount`
* - `_orders[_orderId].sellAmount >= buyAmount`
*
*/
function fillOrder(uint256 _id, address _buyer, uint256 _erc1155Value) external payable {
_Order memory order = _orders[_id];
require(msg.value == order.unitPrice * (_erc1155Value == 0 ? 1 : _erc1155Value));
// subtracting user-suplied `_erc1155Value` from order amount,
// transaction will revert if underflow, implicitly
// requiring `_orders[_id]._erc1155Value >= _erc1155Value`
if (_orders[_id].erc1155Value - _erc1155Value == 0) delete _orders[_id];
else _orders[_id].erc1155Value -= _erc1155Value;
_trade(
_Order(
order.tokenId, // uint256 tokenId
msg.value, // price
_erc1155Value,
order.collection, // address collection
order.from, // seller or from
_buyer, // address buyer used for nft transfer
order.commissionBps, // uint256 commissionBps
order.commissionReceivers // address commissionReceiver
),
_id,
_primaryOrdersFee // uint256 primaryFee
);
}
/**
*
* @dev Handles the receipt of a single ERC1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been
* updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param _operator The address which initiated the transfer (i.e.
* msg.sender)
* @param _from The address which previously owned the token
* @param _tokenId The ID of the token being transferred
* @param _value The amount of tokens being transferred
* @param _data Additional data with no specified format
* @param _data `uint256 id` corresponding to an order to be updated or
* an offer to be accepted, if the `id`
* parameter is 0 create a new order.
* @param _data `uint256 unitPrice` is only required for updating an
* order, i.e. if `unitPrice == 0` `id` an
* offer id, if `unitPrice > 0` `id` is an order id
* @return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* if transfer is allowed
*/
function onERC1155Received(
address _operator, // either the previous owner or operator, whoever
// called safeTransferFrom on the ERC1155
// contract
address _from, // previous owner
uint256 _tokenId,
uint256 _value,
bytes memory _data
)
external
returns (bytes4)
{
(uint256 id, uint256 unitPrice, uint256[] memory commissionBps, address[] memory commissionReceivers) =
abi.decode(_data, (uint256, uint256, uint256[], address[]));
if (unitPrice == 0) {
/*----------------------------------------------------------*|
|* # ACCEPT OFFER *|
|*----------------------------------------------------------*/
// if `_value` is more than the amount the following if check will
// revert due to underflow,
// intended to stop someone from sending more erc1155 tokens then
// there are available in the order
_Offer memory offer = offers[id];
require(offer.collection == msg.sender && offer.tokenId == _tokenId);
// subtracting `_value` from offer amount, transaction will revert
// if underflow, implicitly requiring
// `offers[id]._erc1155Value >= _value`
if (offers[id].erc1155Value - _value == 0) delete offers[id];
else offers[id].erc1155Value -= _value;
_trade(
_Order(
_tokenId, // uint256 tokenId
offer.unitPrice * _value, // uint256 price (unitPrice *
// value)
_value,
msg.sender, // address collection
_from, // seller
offer.from, // buyer or operator
commissionBps, // uint256 commissionBps
commissionReceivers // address commissionReceivers
),
id,
_primaryOffersFee
);
} else if (id == 0) {
/*----------------------------------------------------------*|
|* # CREATE ORDER *|
|*----------------------------------------------------------*/
// if the order/offer id parameter is 0, create a new order
_createOrder(_operator, _from, _tokenId, _value, unitPrice, commissionBps, commissionReceivers);
} else {
/*----------------------------------------------------------*|
|* # UPDATE ORDER *|
|*----------------------------------------------------------*/
// if the user supplied a non-zero value for `unitPrice` then the
// `id` parameter must correspond to an order
// that needs to be updated
// the operator, collection and tokenId of the NFT received by the
// marketplace must match the ones stored at
// the id provided by the operator
// in order to avoid operators increasing allowance for orders with
// different (more valuable) NFTs
_Order storage order = _orders[id];
require(order.operator == _operator && order.collection == msg.sender && order.tokenId == _tokenId);
order.erc1155Value += _value;
order.unitPrice = unitPrice;
emit OrderUpdated(id);
}
return 0xf23a6e61;
}
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this
* contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the
* recipient, the transfer will be
* reverted.
*
* The selector can be obtained in Solidity with
* `IERC721.onERC721Received.selector`.
* @param _operator The address which called `safeTransferFrom` function
* @param _from The address which previously owned the token
* @param _tokenId The NFT identifier which is being transferred
* @param _data Additional data with no specified format
*/
function onERC721Received(
address _operator,
address _from,
uint256 _tokenId,
bytes calldata _data
)
external
returns (bytes4)
{
(uint256 id, uint256 unitPrice, uint256[] memory commissionBps, address[] memory commissionReceivers) =
abi.decode(_data, (uint256, uint256, uint256[], address[]));
if (id == 0) {
/*----------------------------------------------------------*|
|* # CREATE ORDER *|
|*----------------------------------------------------------*/
// if the order/offer id parameter is 0, create a new order
_createOrder(_operator, _from, _tokenId, 0, unitPrice, commissionBps, commissionReceivers);
} else {
/*----------------------------------------------------------*|
|* # ACCEPT OFFER *|
|*----------------------------------------------------------*/
// if `_value` is more than the amount the following if check will
// revert due to underflow,
// intended to stop someone from sending more erc1155 tokens then
// there are available in the order
_Offer memory offer = offers[id];
require(offer.collection == msg.sender && offer.tokenId == _tokenId);
delete offers[id]; // ERC-721 doesn't have any supply therefore the
// offer may be deleted after accepting the
// offer
_trade(
_Order(
_tokenId, // uint256 tokenId
offer.unitPrice, // uint256 price
0,
msg.sender, // address collection
_from, // address buyer or from
offer.from, // seller
commissionBps, // uint256 commissionBps
commissionReceivers
),
id,
_primaryOffersFee //uint256 primaryFee
);
}
return 0x150b7a02;
}
/**
* @dev ERC-721 tokens are transferred to the buyer via `transferFrom`
* rather than `safeTransferFrom`
* i.e. the caller is responsible to confirm that the recipient is
* capable of receiving ERC721
*/
function _transferNFT(
address _collection,
address _from,
address _to,
uint256 _tokenId,
uint256 _erc1155Value
)
private
{
bool success;
if (_erc1155Value == 0) {
// bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
(success,) = _collection.call(abi.encodeWithSelector(0x42842e0e, _from, _to, _tokenId));
} else {
// bytes4(keccak256('safeTransferFrom(address,address,uint256,uint256,bytes)')) == 0xf242432a
(success,) = _collection.call(abi.encodeWithSelector(0xf242432a, _from, _to, _tokenId, _erc1155Value, ""));
}
require(success);
}
function _trade(_Order memory _order, uint256 _id, uint256 _primaryMarketFee) private {
uint256 marketplaceAmount; // declare `marketplaceAmount`, its value
// will be calculated based on whether it is a
// primary or secondary sale
uint256 sellerAmount = _order.unitPrice; // sellerAmount is set equal to
// price and reduced at each step by
// subtracting fees, royalties and commissions, if any.
address payable[] memory royaltyRecipients; // declare
// `royaltyRecipients`, its value will be calculated based
// on whether it is a primary or secondary sale
uint256[] memory royaltyAmounts; // declare `royaltyAmounts`, its value
// will be calculated based on whether it
// is a primary or secondary sale
bool checkSecondaryMarket = true;
if (_order.collection.codehash == _ERC721SovreignV1CodeHash) {
// it's a v1 721 token, check market registry
(, bytes memory secondaryMarket) = _PRIMARY_MARKET_REGISTRY.call(
abi.encodeWithSelector(
0x7abab711,
_order.collection,
_order.tokenId
) // bytes4(keccak256("secondaryMarketInfo(address,uint256)")) == 0x7abab711
);
checkSecondaryMarket = abi.decode(secondaryMarket, (bool));
}
/*----------------------------------------------------------*|
|* # PAY ROYALTIES *|
|*----------------------------------------------------------*/
// > "Marketplaces that support this standard MUST pay royalties no
// matter where the sale occurred or in what
// currency" - https://eips.ethereum.org/EIPS/eip-2981.
/*----------------------------------------------------------*|
|* # IF ROYALTIES SUPPORTED *|
|*----------------------------------------------------------*/
// The collection implements some royalty standard, otherwise the length
// of the arrays returned would be 0.
if (checkSecondaryMarket) {
(royaltyRecipients, royaltyAmounts) = getRoyalty(_order.collection, _order.tokenId, _order.unitPrice);
}
uint256 royaltyRecipientsLength = royaltyRecipients.length; // assign to
// memory variable to save gas
if (royaltyRecipientsLength > 0) {
if (_secondaryMarketFee > 0) {
/*----------------------------------------------------------*|
|* # PAY MARKETPLACE FEE *|
|*----------------------------------------------------------*/
marketplaceAmount = (_order.unitPrice * _secondaryMarketFee) / _BPS_DENOMINATOR;
// subtracting primary or secondary fee amount from seller
// amount, this is a security check (will revert
// on underflow) as well as a variable assignment.
sellerAmount -= marketplaceAmount; // subtract before external
// call
_sendValue(_feeRecipient, marketplaceAmount);
}
do {
royaltyRecipientsLength--;
// subtracting royalty amount from seller amount, this is a
// security check (will revert on
// underflow) as well as a variable assignment.
if(royaltyAmounts[royaltyRecipientsLength] > 0){
sellerAmount -= royaltyAmounts[royaltyRecipientsLength]; // subtract
// before external call
_sendValue(royaltyRecipients[royaltyRecipientsLength], royaltyAmounts[royaltyRecipientsLength]);
}
} while (royaltyRecipientsLength > 0);
} else {
//case primary
marketplaceAmount = (_order.unitPrice * _primaryMarketFee) / _BPS_DENOMINATOR;
sellerAmount -= marketplaceAmount; // subtract before external
// call
_sendValue(_feeRecipient, marketplaceAmount);
}
/*----------------------------------------------------------*|
|* # PAY ORDER COMMISSIONS (if any) *|
|*----------------------------------------------------------*/
uint256 commissionReceiversLength = _order.commissionReceivers.length; // assign
if (commissionReceiversLength > 0) {
do {
commissionReceiversLength--;
if(_order.commissionBps[commissionReceiversLength] > 0){
uint256 commissionAmount = (_order.commissionBps[commissionReceiversLength] * _order.unitPrice) / _BPS_DENOMINATOR; // calculate
sellerAmount -= commissionAmount; // subtract before external
_sendValue(_order.commissionReceivers[commissionReceiversLength], commissionAmount);
}
} while (commissionReceiversLength > 0);
}
/*----------------------------------------------------------*|
|* # PAY SELLER *|
|*----------------------------------------------------------*/
_sendValue(_order.from, sellerAmount);
/*----------------------------------------------------------*|
|* # TRANSFER NFT *|
|*----------------------------------------------------------*/
_transferNFT(
_order.collection,
address(this),
_order.operator, // buyer
_order.tokenId,
_order.erc1155Value
);
emit Trade(
_order.collection,
_order.tokenId,
_order.from, // seller
_id,
_order.unitPrice,
_order.erc1155Value
);
}
/**
* @dev Replacement for Solidity's `transfer`: sends `_amount` wei to
* `_receiver`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] raises the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {_sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn
* more].
*
* IMPORTANT: because control is transferred to `_receiver`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions
* pattern].
*/
function _sendValue(address _receiver, uint256 _amount) private {
// solhint-disable-next-line avoid-low-level-calls
(bool success,) = payable(_receiver).call{ value: _amount }("");
require(success);
}
/*----------------------------------------------------------*|
|* # ADMIN FUNCTIONS *|
|*----------------------------------------------------------*/
/**
* @param feeRecipient_ address (multisig) controlled by Ninfa that will
* receive any market fees
*/
function setFeeRecipient(address feeRecipient_) external onlyOwner {
_feeRecipient = feeRecipient_;
}
/**
* @notice sets market sale fees for NINFA_ERC721_V2 communal collection.
* @param primaryOrdersFee_ fee BPS for primary market orders, set to 500
* BPS (5% shares) at deployment.
* @param primaryOffersFee_ fee BPS for primary market offers, set to 500
* BPS (5% shares) at deployment.
*/
function setMarketFees(
uint256 primaryOrdersFee_,
uint256 primaryOffersFee_,
uint256 secondaryMarketFee_
)
external
onlyOwner
{
_primaryOrdersFee = primaryOrdersFee_;
_primaryOffersFee = primaryOffersFee_;
_secondaryMarketFee = secondaryMarketFee_;
}
function orders(uint256 _orderId) external view returns (_Order memory) {
return _orders[_orderId];
}
/*----------------------------------------------------------*|
|* # VIEW FUNCTIONS *|
|*----------------------------------------------------------*/
/**
* @dev See {IERC165-supportsInterface}.
* Interface ID for IERC165 == 0x01ffc9a7
* Return value from `onERC1155Received` call if a contract accepts receipt
* (i.e
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`).
* In all other cases the ERC1155TokenReceiver rules MUST be followed as
* appropriate for the implementation (i.e.
* safe, custom and/or hybrid).
* Interface ID for IERC721Receiver. A wallet/broker/auction application
* MUST implement the wallet interface if it
* will accept safe transfers.
*/
function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
return interfaceId == 0x01ffc9a7 || interfaceId == 0xf23a6e61 || interfaceId == 0x150b7a02;
}
/*----------------------------------------------------------*|
|* # CONSTRUCTOR *|
|*----------------------------------------------------------*/
/**
* @dev Grants `DEFAULT_ADMIN_ROLE`
* @param _royaltyRegistry see https://royaltyregistry.xyz/lookup for public
* addresses
*/
constructor(
address _royaltyRegistry,
address _primaryMarketRegistry,
bytes32 ERC721SovreignV1CodeHash
)
RoyaltyEngineV1(_royaltyRegistry)
{
_PRIMARY_MARKET_REGISTRY = _primaryMarketRegistry;
_ERC721SovreignV1CodeHash = ERC721SovreignV1CodeHash;
}
}/*----------------------------------------------------------*|
|* ███ ██ ██ ███ ██ ███████ █████ *|
|* ████ ██ ██ ████ ██ ██ ██ ██ *|
|* ██ ██ ██ ██ ██ ██ ██ █████ ███████ *|
|* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ *|
|* ██ ████ ██ ██ ████ ██ ██ ██ *|
|*----------------------------------------------------------*/
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/**
*
* @title Counters *
* *
* @dev Stripped down version of OpenZeppelin Contracts *
* v4.4.1 (utils/Counters.sol), identical to *
* CountersUpgradeable.sol being a library. Provides *
* counters that can only be incremented. *
* Used to track the total supply of ERC721 ids. *
* @dev Include with `using Counters for Counters.Counter;` *
* *
* @custom:security-contact tech@ninfa.io *
*
*/
/**
* @title Counters
* @dev Stripped down version of OpenZeppelin Contracts v4.4.1
* (utils/Counters.sol), identical to
* CountersUpgradeable.sol being a library. Provides counters that can only be
* incremented. Used to track the total
* supply of ERC721 ids.
* @dev Include with `using Counters for Counters.Counter;`
*/
library Counters {
struct Counter {
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
/// @dev if implementing ERC721A there could be an overflow risk by removing
/// overflow protection with `unchecked`,
/// unless we limit the amount of tokens that can be minted, or require that
/// totalsupply be less than 2^256 - 1
function increment(Counter storage counter) internal {
unchecked {
counter._value += 1;
}
}
}/*----------------------------------------------------------*|
|* ███ ██ ██ ███ ██ ███████ █████ *|
|* ████ ██ ██ ████ ██ ██ ██ ██ *|
|* ██ ██ ██ ██ ██ ██ ██ █████ ███████ *|
|* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ *|
|* ██ ████ ██ ██ ████ ██ ██ ██ *|
|*----------------------------------------------------------*/
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import "./specs/IRoyaltyRegistry.sol";
import "./specs/IRoyaltySplitter.sol";
import "./specs/IManifold.sol";
import "./specs/IRarible.sol";
import "./specs/IFoundation.sol";
import "./specs/ISuperRare.sol";
import "./specs/IEIP2981.sol";
import "./specs/INinfaRoyalty.sol";
import "./specs/IZoraOverride.sol";
import "./specs/IArtBlocksOverride.sol";
import "./specs/IKODAV2Override.sol";
/**
*
* @title RoyaltyEngineV1 *
* *
* @notice Custom implementation of Manifold RoyaltyEngineV1 *
* *
* @dev > "Marketplaces may choose to directly inherit the *
* Royalty Engine to save a bit of gas". *
* *
* @dev ERC165 was removed because interface selector will *
* be different from Manifold's (0xcb23f816) and this engine *
* implementation is not meant for used by other contracts *
* *
* @author Fork of Manifold's RoyaltyRegistryV1 *
* *
* @custom:security-contact tech@ninfa.io *
*
*/
contract RoyaltyEngineV1 {
/**
* @dev ROYALTY_REGISTRY could be a hardcoded constant, however using an
* immutable variable
* is useful for deploying the engine onto other (test) networks where its
* address differs from Mainnet
*/
address internal immutable ROYALTY_REGISTRY;
address internal constant SUPERRARE_REGISTRY = 0x17B0C8564E53f22364A6C8de6F7ca5CE9BEa4e5D;
address internal constant SUPERRARE_V1 = 0x41A322b28D0fF354040e2CbC676F0320d8c8850d;
address internal constant SUPERRARE_V2 = 0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0;
error Unauthorized();
error InvalidAmount(uint256 amount);
error LengthMismatch(uint256 recipients, uint256 bps); // only used in
// RoyaltyEngineV1
/**
* Get the royalties for a given token and sale amount.
*
* @param tokenAddress - address of token
* @param tokenId - id of token
* @param value - sale value of token
* Returns two arrays, first is the list of royalty recipients, second is
* the amounts for each recipient.
*/
function getRoyalty(
address tokenAddress,
uint256 tokenId,
uint256 value
)
internal
returns (address payable[] memory recipients, uint256[] memory amounts)
{
/**
* @dev Control-flow hijack and gas griefing vulnerability within
* Manifold's RoyaltyEngine, mitigated in
* https://github.com/manifoldxyz/royalty-registry-solidity/commit/c5ba6db3e04e0b364f7afd7aae853a25542a7439.
* "To mitigate the griefing vector and other potential
* vulnerabilities, limit the gas by default that
* _getRoyalty is given to at most 50,000 gas, but certainly no more
* than 100,000 gas."
* -
* https://githubrecord.com/issue/manifoldxyz/royalty-registry-solidity/17/1067105243
* However, Ninfa's ERC-2981 implementation (ERC2981N) needs to write to
* storage upon primary sales, this consumes
* 800,000 at most gas,
* while it only reads from storage upon secondary sales, see
* {ERC2981N-rotaltyInfo}
*/
try this._getRoyalty{ gas: 1_000_000 }(tokenAddress, tokenId, value) returns (
address payable[] memory _recipients, uint256[] memory _amounts
) {
return (_recipients, _amounts);
} catch {
revert("Royalty lookup failed");
}
}
/**
* @dev Get the royalty for a given token
* @dev the original RoyaltyEngineV1 has been modified by removing the
* _specCache and the associated code,
* using try catch statements is very cheap, no need to store `_specCache`
* mapping, see
* {RoyaltyEngineV1-_specCache}.
* - https://www.reddit.com/r/ethdev/comments/szot8r/comment/hy5vsxb/
* @dev EIP-2981 standard lookup is performed first unlike Manifold's
* implementation, as it is the most prevalent
* royalty standard as well as the one being used by Ninfa's collections
* @return recipients array and amounts array, if no royalty standard has
* been found, the returned arrays will be
* empty
*/
function _getRoyalty(
address tokenAddress,
uint256 tokenId,
uint256 value
)
external
returns (address payable[] memory recipients, uint256[] memory amounts)
{
address royaltyAddress = IRoyaltyRegistry(ROYALTY_REGISTRY).getRoyaltyLookupAddress(tokenAddress);
try INinfaRoyalty(royaltyAddress).ninfaRoyaltyInfo(tokenId, value) returns (
address payable[] memory recipients_, uint256[] memory bps_
) {
require(recipients_.length == bps_.length);
return (recipients_, _computeAmounts(value, bps_));
} catch { }
try IEIP2981(royaltyAddress).royaltyInfo(tokenId, value) returns (address recipient, uint256 amount) {
if (amount > value) revert InvalidAmount(amount);
uint32 recipientSize;
assembly {
recipientSize := extcodesize(recipient)
}
if (recipientSize > 0) {
try IRoyaltySplitter(recipient).getRecipients() returns (Recipient[] memory splitRecipients) {
recipients = new address payable[](splitRecipients.length);
amounts = new uint256[](splitRecipients.length);
uint256 sum = 0;
uint256 splitRecipientsLength = splitRecipients.length;
for (uint256 i = 0; i < splitRecipientsLength;) {
Recipient memory splitRecipient = splitRecipients[i];
recipients[i] = payable(splitRecipient.recipient);
uint256 splitAmount = splitRecipient.bps * amount / 10_000;
amounts[i] = splitAmount;
sum += splitAmount;
unchecked {
++i;
}
}
// sum can be less than amount, otherwise small-value listings can break
require(sum <= amount, "Invalid split");
return (recipients, amounts);
} catch {}
}
try
IRoyaltySplitter(royaltyAddress).getRecipients(tokenId)
returns (Recipient[] memory royaltyInfo) {
uint256 splitRecipientsLength = royaltyInfo.length;
recipients = new address payable[](splitRecipientsLength);
amounts = new uint256[](splitRecipientsLength);
uint256 sum;
for (uint256 i; i < splitRecipientsLength; ) {
Recipient memory splitRecipient = royaltyInfo[i];
recipients[i] = payable(splitRecipient.recipient);
uint256 splitAmount = (splitRecipient.bps * amount) / 10000;
amounts[i] = splitAmount;
sum += splitAmount;
unchecked {
++i;
}
}
// sum can be less than amount, otherwise small-value listings can break
require(sum <= amount, "Invalid split");
return (recipients, amounts);
} catch {
// Supports EIP2981. Return amounts
recipients = new address payable[](1);
amounts = new uint256[](1);
recipients[0] = payable(recipient);
amounts[0] = amount;
return (recipients, amounts);
}
} catch { }
try IManifold(royaltyAddress).getRoyalties(tokenId) returns (
address payable[] memory recipients_, uint256[] memory bps
) {
// Supports manifold interface. Compute amounts
require(recipients_.length == bps.length);
return (recipients_, _computeAmounts(value, bps));
} catch { }
// SuperRare handling
if (tokenAddress == SUPERRARE_V1 || tokenAddress == SUPERRARE_V2) {
try ISuperRareRegistry(SUPERRARE_REGISTRY).tokenCreator(tokenAddress, tokenId) returns (
address payable creator
) {
try ISuperRareRegistry(SUPERRARE_REGISTRY).calculateRoyaltyFee(tokenAddress, tokenId, value) returns (
uint256 amount
) {
recipients = new address payable[](1);
amounts = new uint256[](1);
recipients[0] = creator;
amounts[0] = amount;
return (recipients, amounts);
} catch { }
} catch { }
}
try IRaribleV2(royaltyAddress).getRaribleV2Royalties(tokenId) returns (IRaribleV2.Part[] memory royalties) {
// Supports rarible v2 interface. Compute amounts
recipients = new address payable[](royalties.length);
amounts = new uint256[](royalties.length);
uint256 totalAmount;
for (uint256 i = 0; i < royalties.length; i++) {
recipients[i] = royalties[i].account;
amounts[i] = (value * royalties[i].value) / 10_000;
totalAmount += amounts[i];
}
if (totalAmount > value) revert InvalidAmount(totalAmount);
return (recipients, amounts);
} catch { }
try IRaribleV1(royaltyAddress).getFeeRecipients(tokenId) returns (address payable[] memory recipients_) {
// Supports rarible v1 interface. Compute amounts
recipients_ = IRaribleV1(royaltyAddress).getFeeRecipients(tokenId);
try IRaribleV1(royaltyAddress).getFeeBps(tokenId) returns (uint256[] memory bps) {
if (recipients_.length != bps.length) {
revert LengthMismatch(recipients_.length, bps.length);
}
return (recipients_, _computeAmounts(value, bps));
} catch { }
} catch { }
try IFoundation(royaltyAddress).getFees(tokenId) returns (
address payable[] memory recipients_, uint256[] memory bps
) {
// Supports foundation interface. Compute amounts
if (recipients_.length != bps.length) {
revert LengthMismatch(recipients_.length, bps.length);
}
return (recipients_, _computeAmounts(value, bps));
} catch { }
try IZoraOverride(royaltyAddress).convertBidShares(tokenAddress, tokenId) returns (
address payable[] memory recipients_, uint256[] memory bps
) {
// Support Zora override
if (recipients_.length != bps.length) {
revert LengthMismatch(recipients_.length, bps.length);
}
return (recipients_, _computeAmounts(value, bps));
} catch { }
try IArtBlocksOverride(royaltyAddress).getRoyalties(tokenAddress, tokenId) returns (
address payable[] memory recipients_, uint256[] memory bps
) {
// Support Art Blocks override
if (recipients_.length != bps.length) {
revert LengthMismatch(recipients_.length, bps.length);
}
return (recipients_, _computeAmounts(value, bps));
} catch { }
try IKODAV2Override(royaltyAddress).getKODAV2RoyaltyInfo(tokenAddress, tokenId, value) returns (
address payable[] memory _recipients, uint256[] memory _amounts
) {
// Support KODA V2 override
if (_recipients.length != _amounts.length) {
revert LengthMismatch(_recipients.length, _amounts.length);
}
return (_recipients, _amounts);
} catch { }
// No supported royalties configured
return (recipients, amounts);
}
/**
* Compute royalty amounts
*/
function _computeAmounts(uint256 value, uint256[] memory bps) private pure returns (uint256[] memory amounts) {
amounts = new uint256[](bps.length);
uint256 totalAmount;
for (uint256 i = 0; i < bps.length; i++) {
amounts[i] = (value * bps[i]) / 10_000;
totalAmount += amounts[i];
}
if (totalAmount > value) revert InvalidAmount(totalAmount);
return amounts;
}
constructor(address _royaltyRegistry) {
ROYALTY_REGISTRY = _royaltyRegistry;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable {
address private _owner;
event OwnershipTransferred(address previousOwner, address newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(msg.sender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == msg.sender);
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() external onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0));
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/// @author: manifold.xyz
import "../introspection/IERC165.sol";
/**
* @dev Royalty registry interface
*/
interface IRoyaltyRegistry is IERC165 {
event RoyaltyOverride(address owner, address tokenAddress, address royaltyAddress);
/**
* Override the location of where to look up royalty information for a given
* token contract.
* Allows for backwards compatibility and implementation of royalty logic
* for contracts that did not previously
* support them.
*
* @param tokenAddress - The token address you wish to override
* @param royaltyAddress - The royalty override address
*/
function setRoyaltyLookupAddress(address tokenAddress, address royaltyAddress) external returns (bool);
/**
* Returns royalty address location. Returns the tokenAddress by default,
* or the override if it exists
*
* @param tokenAddress - The token address you are looking up the royalty
* for
*/
function getRoyaltyLookupAddress(address tokenAddress) external view returns (address);
/**
* Returns the token address that an overrideAddress is set for.
* Note: will not be accurate if the override was created before this
* function was added.
*
* @param overrideAddress - The override address you are looking up the
* token for
*/
function getOverrideLookupTokenAddress(address overrideAddress) external view returns (address);
/**
* Whether or not the message sender can override the royalty address for
* the given token address
*
* @param tokenAddress - The token address you are looking up the royalty
* for
*/
function overrideAllowed(address tokenAddress) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/// @author: manifold.xyz
struct Recipient {
address payable recipient;
uint16 bps;
}
interface IRoyaltySplitter {
/**
* @dev Get the splitter recipients;
*/
function getRecipients() external view returns (Recipient[] memory);
function getRecipients(
uint256 tokenId
) external view returns (Recipient[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/// @author: manifold.xyz
/**
* @dev Royalty interface for creator core classes
*/
interface IManifold {
/**
* @dev Get royalites of a token. Returns list of receivers and basisPoints
*
* bytes4(keccak256('getRoyalties(uint256)')) == 0xbb3bafd6
*
* => 0xbb3bafd6 = 0xbb3bafd6
*/
function getRoyalties(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
interface IRaribleV1 {
/*
* bytes4(keccak256('getFeeBps(uint256)')) == 0x0ebd4c7f
* bytes4(keccak256('getFeeRecipients(uint256)')) == 0xb9c4d9fb
*
* => 0x0ebd4c7f ^ 0xb9c4d9fb == 0xb7799584
*/
function getFeeBps(uint256 id) external view returns (uint256[] memory);
function getFeeRecipients(uint256 id) external view returns (address payable[] memory);
}
interface IRaribleV2 {
/*
* bytes4(keccak256('getRaribleV2Royalties(uint256)')) == 0xcad96cca
*/
struct Part {
address payable account;
uint96 value;
}
function getRaribleV2Royalties(uint256 id) external view returns (Part[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
interface IFoundation {
/*
* bytes4(keccak256('getFees(uint256)')) == 0xd5a06d4c
*
* => 0xd5a06d4c = 0xd5a06d4c
*/
function getFees(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory);
}
interface IFoundationTreasuryNode {
function getFoundationTreasury() external view returns (address payable);
}
interface IFoundationTreasury {
function isAdmin(address account) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
interface ISuperRareRegistry {
/**
* @dev Get the royalty fee percentage for a specific ERC721 contract.
* @param _contractAddress address ERC721Contract address.
* @param _tokenId uint256 token ID.
* @return uint8 wei royalty fee.
*/
function getERC721TokenRoyaltyPercentage(
address _contractAddress,
uint256 _tokenId
)
external
view
returns (uint8);
/**
* @dev Utililty function to calculate the royalty fee for a token.
* @param _contractAddress address ERC721Contract address.
* @param _tokenId uint256 token ID.
* @param _amount uint256 wei amount.
* @return uint256 wei fee.
*/
function calculateRoyaltyFee(
address _contractAddress,
uint256 _tokenId,
uint256 _amount
)
external
view
returns (uint256);
/**
* @dev Get the token creator which will receive royalties of the given
* token
* @param _contractAddress address ERC721Contract address.
* @param _tokenId uint256 token ID.
*/
function tokenCreator(address _contractAddress, uint256 _tokenId) external view returns (address payable);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/**
* EIP-2981
*/
interface IEIP2981 {
/**
* bytes4(keccak256("royaltyInfo(uint256,uint256)")) == 0x2a55205a
*
* => 0x2a55205a = 0x2a55205a
*/
function royaltyInfo(uint256 tokenId, uint256 value) external view returns (address, uint256);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/**
* EIP-2981
*/
interface INinfaRoyalty {
/**
* bytes4(keccak256("royaltyInfo(uint256,uint256)")) == 0x2a55205a
*
* => 0x2a55205a = 0x2a55205a
*/
function ninfaRoyaltyInfo(
uint256 tokenId,
uint256 value
)
external
returns (address payable[] memory, uint256[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/**
* Paired down version of the Zora Market interface
*/
interface IZoraMarket {
struct ZoraDecimal {
uint256 value;
}
struct ZoraBidShares {
// % of sale value that goes to the _previous_ owner of the nft
ZoraDecimal prevOwner;
// % of sale value that goes to the original creator of the nft
ZoraDecimal creator;
// % of sale value that goes to the seller (current owner) of the nft
ZoraDecimal owner;
}
function bidSharesForToken(uint256 tokenId) external view returns (ZoraBidShares memory);
}
/**
* Paired down version of the Zora Media interface
*/
interface IZoraMedia {
/**
* Auto-generated accessors of public variables
*/
function marketContract() external view returns (address);
function previousTokenOwners(uint256 tokenId) external view returns (address);
function tokenCreators(uint256 tokenId) external view returns (address);
/**
* ERC721 function
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
}
/**
* Interface for a Zora media override
*/
interface IZoraOverride {
/**
* @dev Convert bid share configuration of a Zora Media token into an array
* of receivers and bps values
* Does not support prevOwner and sell-on amounts as that is specific
* to Zora marketplace implementation
* and requires updates on the Zora Media and Marketplace to update the
* sell-on amounts/previous owner values.
* An off-Zora marketplace sale will break the sell-on functionality.
*/
function convertBidShares(
address media,
uint256 tokenId
)
external
view
returns (address payable[] memory, uint256[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/**
* Interface for an Art Blocks override
*/
interface IArtBlocksOverride {
/**
* @dev Get royalites of a token at a given tokenAddress.
* Returns array of receivers and basisPoints.
*
* bytes4(keccak256('getRoyalties(address,uint256)')) == 0x9ca7dc7a
*
* => 0x9ca7dc7a = 0x9ca7dc7a
*/
function getRoyalties(
address tokenAddress,
uint256 tokenId
)
external
view
returns (address payable[] memory, uint256[] memory);
}// SPDX-License-Identifier: MIT
/// @author: knownorigin.io
pragma solidity 0.8.20;
interface IKODAV2 {
function editionOfTokenId(uint256 _tokenId) external view returns (uint256 _editionNumber);
function artistCommission(uint256 _editionNumber)
external
view
returns (address _artistAccount, uint256 _artistCommission);
function editionOptionalCommission(uint256 _editionNumber)
external
view
returns (uint256 _rate, address _recipient);
}
interface IKODAV2Override {
/// @notice Emitted when the royalties fee changes
event CreatorRoyaltiesFeeUpdated(uint256 _oldCreatorRoyaltiesFee, uint256 _newCreatorRoyaltiesFee);
/// @notice For the given KO NFT and token ID, return the addresses and the
/// amounts to pay
function getKODAV2RoyaltyInfo(
address _tokenAddress,
uint256 _id,
uint256 _amount
)
external
view
returns (address payable[] memory, uint256[] memory);
/// @notice Allows the owner() to update the creator royalties
function updateCreatorRoyalties(uint256 _creatorRoyaltiesFee) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP
* section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"remappings": [
"forge-std/=lib/forge-std/src/",
"solmate/=lib/solmate/src/",
"openzeppelin/=lib/openzeppelin-contracts/contracts/",
"src/=src/",
"test/=test/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 4194304,
"details": {
"constantOptimizer": true,
"yul": true,
"yulDetails": {
"stackAllocation": true,
"optimizerSteps": "dhfoDgvulfnTUtnIf"
}
}
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": false
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": true,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_royaltyRegistry","type":"address"},{"internalType":"address","name":"_primaryMarketRegistry","type":"address"},{"internalType":"bytes32","name":"ERC721SovreignV1CodeHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"InvalidAmount","type":"error"},{"inputs":[{"internalType":"uint256","name":"recipients","type":"uint256"},{"internalType":"uint256","name":"bps","type":"uint256"}],"name":"LengthMismatch","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"offerId","type":"uint256"}],"name":"OfferCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"offerId","type":"uint256"}],"name":"OfferDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"offerId","type":"uint256"}],"name":"OfferUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"OrderCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"OrderDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"OrderUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"erc1155Value","type":"uint256"}],"name":"Trade","type":"event"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"_getRoyalty","outputs":[{"internalType":"address payable[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_orderId","type":"uint256"},{"internalType":"uint256","name":"_offerId","type":"uint256"},{"internalType":"uint256[]","name":"_commissionBps","type":"uint256[]"},{"internalType":"address[]","name":"_commissionReceivers","type":"address[]"}],"name":"acceptListedTokenOffer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_unitPrice","type":"uint256"}],"name":"createOffer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_offerId","type":"uint256"}],"name":"deleteOffer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_orderId","type":"uint256"}],"name":"deleteOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"address","name":"_buyer","type":"address"},{"internalType":"uint256","name":"_erc1155Value","type":"uint256"}],"name":"fillOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_offerId","type":"uint256"},{"internalType":"uint256","name":"_erc1155Amount","type":"uint256"},{"internalType":"uint256","name":"_unitPrice","type":"uint256"}],"name":"lowerOfferPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_orderId","type":"uint256"},{"internalType":"uint256","name":"_erc1155RedeemAmount","type":"uint256"}],"name":"lowerOrderErc1155Amount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"offers","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"unitPrice","type":"uint256"},{"internalType":"uint256","name":"erc1155Value","type":"uint256"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"from","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_orderId","type":"uint256"}],"name":"orders","outputs":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"unitPrice","type":"uint256"},{"internalType":"uint256","name":"erc1155Value","type":"uint256"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256[]","name":"commissionBps","type":"uint256[]"},{"internalType":"address[]","name":"commissionReceivers","type":"address[]"}],"internalType":"struct NinfaMarketplace._Order","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_offerId","type":"uint256"},{"internalType":"uint256","name":"_erc1155Value","type":"uint256"},{"internalType":"uint256","name":"_unitPrice","type":"uint256"}],"name":"raiseOfferPrice","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feeRecipient_","type":"address"}],"name":"setFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"primaryOrdersFee_","type":"uint256"},{"internalType":"uint256","name":"primaryOffersFee_","type":"uint256"},{"internalType":"uint256","name":"secondaryMarketFee_","type":"uint256"}],"name":"setMarketFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_orderId","type":"uint256"},{"internalType":"uint256[]","name":"_commissionBps","type":"uint256[]"},{"internalType":"address[]","name":"_commissionReceivers","type":"address[]"}],"name":"setOrderCommission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_erc1155RedeemAmount","type":"uint256"},{"internalType":"uint256","name":"_unitPrice","type":"uint256"},{"internalType":"uint256","name":"_orderId","type":"uint256"}],"name":"updateOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_orderId","type":"uint256"},{"internalType":"uint256","name":"_unitPrice","type":"uint256"}],"name":"updateOrderPrice","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c06040523462000043576200001f620000186200011d565b9162000172565b6040516142136200026e82396080518161365d015260a05181612cdd015261421390f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b90601f01601f191681019081106001600160401b038211176200008057604052565b62000048565b906200009d6200009560405190565b92836200005e565b565b6001600160a01b031690565b90565b6001600160a01b0381165b036200004357565b905051906200009d82620000ae565b80620000b9565b905051906200009d82620000d0565b90916060828403126200004357620000ab620001038484620000c1565b93620001138160208601620000c1565b93604001620000d7565b620001406200448180380380620001348162000086565b928339810190620000e6565b909192565b90600019905b9181191691161790565b9062000166620000ab6200016e9290565b825462000145565b9055565b90620001836200009d93926200018e565b60a052600762000155565b620001986200019d565b608052565b6200009d3362000200565b906001600160a01b03906200014b565b620000ab906200009f906001600160a01b031682565b620000ab90620001b8565b620000ab90620001ce565b90620001f8620000ab6200016e92620001d9565b8254620001a8565b6000546001600160a01b0316906200021a816000620001e4565b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091620002686200024a60405190565b928392836001600160a01b0391821681529116602082015260400190565b0390a156fe6080604052600436101561001257600080fd5b60003560e01c806301ffc9a71461017257806311a003271461016d578063150b7a021461016857806317a288df146101635780631efeff841461015e5780632b1708b0146101595780632ede65df1461015457806332689eb81461014f5780633596188d1461014a5780635333a0a4146101455780635e9e78d014610140578063715018a61461013b57806374268ff2146101365780637fea43b8146101315780638a72ea6a1461012c5780638b4c042a146101275780638da5cb5b14610122578063a85c38ef1461011d578063c402b96514610118578063e74b981b14610113578063f23a6e611461010e5763f2fde38b0361017757610ca6565b610c87565b610b83565b610b58565b610ae5565b610974565b61095b565b61092a565b6107e9565b6106e5565b6106cd565b6106a9565b61068d565b610611565b6105fd565b6105bd565b6105a9565b610560565b610524565b610308565b610225565b6101cd565b600080fd5b7fffffffff0000000000000000000000000000000000000000000000000000000081165b0361017757565b905035906101b48261017c565b565b90602082820312610177576101ca916101a7565b90565b34610177576101fa6101e86101e33660046101b6565b612eaa565b60405191829182901515815260200190565b0390f35b806101a0565b905035906101b4826101fe565b90602082820312610177576101ca91610204565b346101775761023d610238366004610211565b611190565b604051005b73ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff81166101a0565b905035906101b48261025b565b909182601f830112156101775781359167ffffffffffffffff831161017757602001926001830284011161017757565b90608082820312610177576102c98183610277565b926102d78260208501610277565b926102e58360408301610204565b92606082013567ffffffffffffffff8111610177576103049201610284565b9091565b34610177576101fa61032761031e3660046102b4565b93929092612585565b604051918291827fffffffff00000000000000000000000000000000000000000000000000000000909116815260200190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810190811067ffffffffffffffff8211176103c957604052565b61035a565b906101b46103db60405190565b9283610389565b67ffffffffffffffff81116103c95760208091020190565b9092919261040f61040a826103e2565b6103ce565b938185526020808601920283019281841161017757915b8383106104335750505050565b602080916104418486610204565b815201920191610426565b9080601f83011215610177578160206101ca933591016103fa565b9092919261047761040a826103e2565b938185526020808601920283019281841161017757915b83831061049b5750505050565b602080916104a98486610277565b81520192019161048e565b9080601f83011215610177578160206101ca93359101610467565b91606083830312610177576104e48284610204565b92602081013567ffffffffffffffff8111610177578361050591830161044c565b92604082013567ffffffffffffffff8111610177576101ca92016104b4565b346101775761023d6105373660046104cf565b9161160c565b9190604083820312610177576101ca906105578185610204565b93602001610204565b346101775761023d61057336600461053d565b906113ce565b9091606082840312610177576101ca6105928484610204565b936105a08160208601610204565b93604001610204565b61023d6105b7366004610579565b916119fe565b346101775761023d6105d0366004610579565b91610d07565b9091606082840312610177576101ca6105ef8484610204565b936105a08160208601610277565b61023d61060b3660046105d6565b91611df8565b346101775761023d610624366004610579565b91612e43565b906080828203126101775761063f8183610204565b9261064d8260208501610204565b92604081013567ffffffffffffffff8111610177578361066e91830161044c565b92606082013567ffffffffffffffff8111610177576101ca92016104b4565b346101775761023d6106a036600461062a565b92919091611c19565b346101775761023d6106bc36600461053d565b9061127f565b600091031261017757565b34610177576106dd3660046106c2565b61023d612fb4565b346101775761023d6106f8366004610211565b61190e565b9091606082840312610177576101ca6105928484610277565b0190565b9061073a610733610729845190565b8084529260200190565b9260200190565b9060005b81811061074b5750505090565b90919261077e610777600192865173ffffffffffffffffffffffffffffffffffffffff16815260200190565b9460200190565b92910161073e565b90610795610733610729845190565b9060005b8181106107a65750505090565b9091926107bc6107776001928651815260200190565b929101610799565b60408082526101ca9391926107db9184019061071a565b916020818403910152610786565b34610177576108026107fc3660046106fd565b91613648565b906101fa61080f60405190565b928392836107c4565b6101ca6101ca6101ca9290565b9061082f90610818565b600052602052604060002090565b6101ca9081565b6101ca905461083d565b610859906009610825565b61086281610844565b9161086f60018301610844565b9161087c60028201610844565b916101ca60046108a3600385015473ffffffffffffffffffffffffffffffffffffffff1690565b93015473ffffffffffffffffffffffffffffffffffffffff1690565b909594926101b4946108f161090e926108ea6080966108e360a088019c6000890152565b6020870152565b6040850152565b73ffffffffffffffffffffffffffffffffffffffff166060830152565b019073ffffffffffffffffffffffffffffffffffffffff169052565b34610177576101fa610945610940366004610211565b61084e565b9161095295939560405190565b958695866108bf565b346101775761023d61096e366004610579565b91611b57565b34610177576109843660046106c2565b6101fa6109a660005473ffffffffffffffffffffffffffffffffffffffff1690565b6040519182918273ffffffffffffffffffffffffffffffffffffffff909116815260200190565b906109dc610733610729845190565b9060005b8181106109ed5750505090565b909192610a19610777600192865173ffffffffffffffffffffffffffffffffffffffff16815260200190565b9291016109e0565b805182526101ca9160e0610ac36101008301610a4260208601516020860152565b610a5160408601516040860152565b60608581015173ffffffffffffffffffffffffffffffffffffffff169085015260808581015173ffffffffffffffffffffffffffffffffffffffff169085015260a08581015173ffffffffffffffffffffffffffffffffffffffff169085015260c085015184820360c0860152610786565b9201519060e08184039101526109cd565b60208082526101ca92910190610a21565b34610177576101fa610b00610afb366004610211565b612e93565b60405191829182610ad4565b919060a08382031261017757610b228184610277565b92610b308260208301610204565b926101ca610b418460408501610204565b93610b4f8160608601610277565b93608001610204565b61023d610b66366004610b0c565b93929092611741565b90602082820312610177576101ca91610277565b346101775761023d610b96366004610b6f565b612df1565b67ffffffffffffffff81116103c957602090601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b90826000939282370152565b90929192610bf261040a82610b9b565b93818552602085019082840111610177576101b492610bd6565b9080601f83011215610177578160206101ca93359101610be2565b91909160a08184031261017757610c3e8382610277565b92610c4c8160208401610277565b92610c5a8260408501610204565b92610c688360608301610204565b92608082013567ffffffffffffffff8111610177576101ca9201610c0c565b34610177576101fa610327610c9d366004610c27565b939290926120d1565b346101775761023d610cb9366004610b6f565b613014565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905b9181191691161790565b90610cfc6101ca610d0392610818565b8254610cbe565b9055565b610d216101b493610d1a600193826113ce565b6008610825565b01610cec565b90610d42610d36610729845490565b92600052602060002090565b9060005b818110610d535750505090565b909192610d77610d70600192610d6887610844565b815260200190565b9460010190565b929101610d46565b906101ca91610d27565b906101b4610da392610d9a60405190565b93848092610d7f565b0383610389565b90610db9610d36610729845490565b9060005b818110610dca5750505090565b909192610e12610d70600192610df4875473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16815260200190565b929101610dbd565b906101ca91610daa565b906101b4610da392610e3560405190565b93848092610e1a565b6101ca6101006103ce565b906101b4610f766007610e5a610e3e565b94610e6b610e6782610844565b8752565b610e81610e7a60018301610844565b6020880152565b610e97610e9060028301610844565b6040880152565b610ed8610ebb600383015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff166060880152565b610f19610efc600483015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff166080880152565b610f5a610f3d600583015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1660a0880152565b610f70610f6960068301610d89565b60c0880152565b01610e24565b60e0840152565b6101ca90610e49565b1561017757565b91906008610ce2910291610fc07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841b90565b921b90565b9190610fd66101ca610d0393610818565b908354610f8d565b6101b491600091610fc5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9190611024565b9290565b9180830292818404149015171561103757565b610fea565b818110611047575050565b806110556000600193610fde565b0161103c565b909182811061106957505050565b6101b4929061107790610d36565b908101910161103c565b906801000000000000000081116103c9578161109e6101b4935490565b9082815561105b565b60006101b491611081565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b906000036110f2576101b4906110a7565b6110b2565b600060076101b49261110b83808301610fde565b6111188360018301610fde565b6111258360028301610fde565b82600382015582600482015582600582015561114483600683016110e1565b016110e1565b906000036110f2576101b4906110f7565b6102426101ca6101ca9273ffffffffffffffffffffffffffffffffffffffff1690565b6101ca9061115b565b6101ca9061117e565b61123f60086111a76111a28483610825565b610f7d565b61120160006111fc8633956111f76111d961024260a089015173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff89165b14610f86565b610825565b61114a565b606081015173ffffffffffffffffffffffffffffffffffffffff169161122630611187565b6112396040611233855190565b94015190565b9361274e565b61127a7f91635156bba825be2f9a200b140420e4bee0d251f7d43bf956e63f74960030e09161126d60405190565b9182918290815260200190565b0390a1565b906112d99060016112946101ca856008610825565b610d21336111f16112bf610242600586015473ffffffffffffffffffffffffffffffffffffffff1690565b9173ffffffffffffffffffffffffffffffffffffffff1690565b61127a7fb8b459bc0688c37baf5f735d17f1711684bc14ab7db116f88bc18bf409b9309a9161126d60405190565b9190820391821161103757565b6113276113216101ca9290565b60e01b90565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b73ffffffffffffffffffffffffffffffffffffffff9182168152911660208201526101ca9260a082019261138b9190611384906108ea565b6060830152565b60808183039101526000815260200190565b906113aa61040a83610b9b565b918252565b3d156113c9576113be3d61139d565b903d6000602084013e565b606090565b80916114db6008916114d66000806113e96101ca8888610825565b60046114be3392611433611417610242600584015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff86166111f1565b6114af60028201986114566114508261144b8d610844565b611307565b8b610cec565b600383015473ffffffffffffffffffffffffffffffffffffffff169563f242432a9061149561148f8a61148830611187565b9701610844565b92611314565b9461149f60405190565b978896602088019081520161134c565b60208201810382520382610389565b82602082019151925af16114d06113af565b50610f86565b610844565b906000916114ef6114eb84610818565b9190565b036115015761123f926111fc91610825565b50505061127a7fb8b459bc0688c37baf5f735d17f1711684bc14ab7db116f88bc18bf409b9309a9161126d60405190565b81519167ffffffffffffffff83116103c95761155d610d366001926115578686611081565b60200190565b92049160005b8381106115705750505050565b60019060206115806101ca865190565b9401938184015501611563565b906101b491611532565b81519167ffffffffffffffff83116103c9576115bc610d366001926115578686611081565b92049160005b8381106115cf5750505050565b60019060206115f56101ca865173ffffffffffffffffffffffffffffffffffffffff1690565b94019381840155016115c2565b906101b491611597565b916007611664846112d9946111f733916116526008936111f16112bf61024260056116378a8a610825565b015473ffffffffffffffffffffffffffffffffffffffff1690565b600661165e8585610825565b0161158d565b01611602565b6101ca60a06103ce565b9073ffffffffffffffffffffffffffffffffffffffff90610ce2565b906116a06101ca610d0392611187565b8254611674565b6101b49190611714906080906004906116c8816116c2875190565b90610cec565b6116da600182016116c2602088015190565b6116ec600282016116c2604088015190565b61171a60038201611714606088015173ffffffffffffffffffffffffffffffffffffffff1690565b90611690565b0192015173ffffffffffffffffffffffffffffffffffffffff1690565b906101b4916116a7565b6117fc94936117c16117de926117a46117f79661179d61175f600290565b996117698b6130ba565b6117966000996117788b610818565b850361182a5761178883346111f1565b61179061166a565b9a8b0152565b6020890152565b6040870152565b73ffffffffffffffffffffffffffffffffffffffff166060850152565b73ffffffffffffffffffffffffffffffffffffffff166080830152565b6117f260096117ec856130a5565b90610825565b611737565b6130a5565b61127a7f682fd9923da5632e7c7702dabcfa626195d5f444833bc25f94e418e258e791869161126d60405190565b61183e346111f16114eb6101ca8988611019565b611788565b906101b46118a3600461185461166a565b94611861610e6782610844565b611870610e7a60018301610844565b61187f610e9060028301610844565b611637610ebb600383015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff166080840152565b6101ca90611843565b6000906004906118d98382610fde565b6118e68360018301610fde565b6118f38360028301610fde565b8260038201550155565b906000036110f2576101b4906118c9565b6119aa60096119a56119286119238584610825565b6118c0565b61198b60408201611937815190565b90876000926119486114eb85610818565b036119d85760208501516119869250965b6111f76080339701966111f16112bf6102428a5173ffffffffffffffffffffffffffffffffffffffff1690565b6118fd565b5173ffffffffffffffffffffffffffffffffffffffff1690565b612d86565b61127a7f88686b85d6f2c3ab9a04e4f15a22fcfa025ffd97226dcf0a67cdf682def556769161126d60405190565b6119f8611986926119f26119ed602089015190565b915190565b90611019565b96611959565b9190611a8691611a81611a156101ca866009610825565b91611a41336111f16112bf610242600488015473ffffffffffffffffffffffffffffffffffffffff1690565b60016002840193611a5185610844565b611a5e6114eb6000610818565b03611ab457610d21346111f16114eb6101ca611a7b878701610844565b88611307565b610cec565b61127a7f7eff4a127d11f41398f54211d23467816d498336249c9103adb206d679f0e4829161126d60405190565b611ae8346111f16114eb6101ca611acb8b89611019565b611ae2611ad9898901610844565b6119f28d610844565b90611307565b610d21565b15611af457565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f68777900000000000000000000000000000000000000000000000000000000006044820152606490fd5b0390fd5b91611a8691611b6a6101ca856009610825565b913391611bb1611b94610242600487015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff851614611aed565b611bbb6000610818565b8103611bde5750806001611bd76119a59361144b838801610844565b9401610cec565b9290600182611ae8611bf4836119a59601610844565b96611c13611c0960028501996119f28b610844565b611ae28388611019565b97610cec565b919290926008611c2c6111a28583610825565b906009611c3c6119238883610825565b96611c5e60a085015173ffffffffffffffffffffffffffffffffffffffff1690565b3393908890611c6c866112bf565b1480611ddd575b80611d89575b611c8290610f86565b611c8b91610825565b6000611c969161114a565b611c9f91610825565b6000611caa916118fd565b815195611cb8602082015190565b60609093015160009073ffffffffffffffffffffffffffffffffffffffff1660809092015173ffffffffffffffffffffffffffffffffffffffff1693611cfc610e3e565b98611d0790838b0152565b6020890152611d1590610818565b604088015273ffffffffffffffffffffffffffffffffffffffff16606087015273ffffffffffffffffffffffffffffffffffffffff16608086015273ffffffffffffffffffffffffffffffffffffffff1660a085015260c084015260e0830152611d7f6005610844565b906101b4926128ed565b50611c828a611dd56112bf6102426060611db9818d015173ffffffffffffffffffffffffffffffffffffffff1690565b94015173ffffffffffffffffffffffffffffffffffffffff1690565b149050611c79565b5089611df26114eb6101ca60006112338b5190565b14611c73565b90916101ca92600890611e0e6111a28584610825565b91843491611e1d602086015190565b90611e48611e4260009a8b94611e3286610818565b8b03611f72576119f26001610818565b856111f1565b611e618761144b6002611e5b8786610825565b01610844565b611e6d6114eb84610818565b03611f4e57611e7f926111fc91610825565b8583015193611ea5606085015173ffffffffffffffffffffffffffffffffffffffff1690565b90611ec7608086015173ffffffffffffffffffffffffffffffffffffffff1690565b9260c08601519560e0015196611edb610e3e565b998a01526020890152604088015273ffffffffffffffffffffffffffffffffffffffff16606087015273ffffffffffffffffffffffffffffffffffffffff16608086015273ffffffffffffffffffffffffffffffffffffffff1660a085015260c084015260e0830152611d7f6004610844565b60029150611f6d92611f5f91610825565b016116c28661144b83610844565b611e7f565b8a90611019565b905051906101b4826101fe565b90929192611f9661040a826103e2565b938185526020808601920283019281841161017757915b838310611fba5750505050565b60208091611fc88486611f79565b815201920191611fad565b9080601f830112156101775781516101ca92602001611f86565b905051906101b48261025b565b9092919261200a61040a826103e2565b938185526020808601920283019281841161017757915b83831061202e5750505050565b6020809161203c8486611fed565b815201920191612021565b9080601f830112156101775781516101ca92602001611ffa565b90608082820312610177576120768183611f79565b926120848260208501611f79565b92604081015167ffffffffffffffff811161017757836120a5918301611fd3565b92606082015167ffffffffffffffff8111610177576101ca9201612047565b9190820180921161103757565b939092906120ee9060206120e3825190565b818301019101612061565b9492959160009491949761210189610818565b82036122895750506009906121196119238884610825565b878961213c606084015173ffffffffffffffffffffffffffffffffffffffff1690565b339590612148876112bf565b1480612272575b61215890610f86565b61216b8561144b6002611e5b8786610825565b6121776114eb84610818565b0361224e576121899261198691610825565b81612195602083015190565b9061219f91611019565b60809091015173ffffffffffffffffffffffffffffffffffffffff16946121c4610e3e565b998a01526020890152604088015273ffffffffffffffffffffffffffffffffffffffff16606087015273ffffffffffffffffffffffffffffffffffffffff16608086015273ffffffffffffffffffffffffffffffffffffffff1660a085015260c084015260e08301526122376005610844565b90612241926128ed565b6101ca63f23a6e61611314565b6002915061226d9261225f91610825565b016116c28461144b83610844565b612189565b506121586122808386015190565b8914905061214f565b909495969761229b8195949395610818565b89036122b157506122ac97506124ac565b612241565b6123419750600195965061232b91949250610d21936122d46101ca8b6008610825565b956123166112bf6122fc60058a015473ffffffffffffffffffffffffffffffffffffffff1690565b9273ffffffffffffffffffffffffffffffffffffffff1690565b149182612393575b82612377575b5050610f86565b6116c2600284019161233c83610844565b6120c4565b61236f7fb8b459bc0688c37baf5f735d17f1711684bc14ab7db116f88bc18bf409b9309a9161126d60405190565b0390a1612241565b61238b9192506110206114eb918801610844565b143880612324565b91506123b6600387015473ffffffffffffffffffffffffffffffffffffffff1690565b6123bf336112bf565b149161231e565b6101b4919061249c9060e0906007906123e1816116c2875190565b6123f3600182016116c2602088015190565b612405600282016116c2604088015190565b61242d60038201611714606088015173ffffffffffffffffffffffffffffffffffffffff1690565b61245560048201611714608088015173ffffffffffffffffffffffffffffffffffffffff1690565b61247d6005820161171460a088015173ffffffffffffffffffffffffffffffffffffffff1690565b6124956006820161248f60c088015190565b9061158d565b0192015190565b90611602565b906101b4916123c6565b919492959360016124bc816130ba565b6124c5906130a5565b9633916124d0610e3e565b9788526020880152604087015273ffffffffffffffffffffffffffffffffffffffff16606086015273ffffffffffffffffffffffffffffffffffffffff16608085015273ffffffffffffffffffffffffffffffffffffffff1660a084015260c083015260e0820152612543826008610825565b9061254d916124a2565b7f7e82078c35b6665b9d320ebeaa6c266960fad5b802c5558cf7df60c4769af95b9061257860405190565b908152806020810161127a565b9261259d919294612594600090565b5081019061062a565b9491926000949194906125af82610818565b81036125d75750906125c46125ca9792610818565b926124ac565b6101ca63150b7a02611314565b95949350915060096125ec6119238783610825565b928061260f606086015173ffffffffffffffffffffffffffffffffffffffff1690565b339390899061261d866112bf565b14806126fc575b61262d90610f86565b61263691610825565b90612640916118fd565b602084015160809094015173ffffffffffffffffffffffffffffffffffffffff169361266a610e3e565b9861267590838b0152565b602089015261268390610818565b604088015273ffffffffffffffffffffffffffffffffffffffff16606087015273ffffffffffffffffffffffffffffffffffffffff16608086015273ffffffffffffffffffffffffffffffffffffffff1660a085015260c084015260e08301526126ed6005610844565b906126f7926128ed565b6125ca565b5061262d8b6127116114eb611020878c015190565b149050612624565b73ffffffffffffffffffffffffffffffffffffffff9182168152911660208201526060810192916101b49160400152565b0152565b906101b4949293600491612760600090565b50600095869561276f87610818565b81036127a557506114be926114af9161278b6342842e0e611314565b9361279560405190565b9687956020870190815201612719565b6114be936114af9261149563f242432a611314565b73ffffffffffffffffffffffffffffffffffffffff90911681526040810192916101b49160200152565b8015156101a0565b905051906101b4826127e4565b90602082820312610177576101ca916127ec565b6101ca612710610818565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8115612851570490565b612818565b8015611037577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906128b9825190565b8110156128ca576020809102010190565b612881565b9081526060810193926101b492909160409161274a905b6020830152565b909160208201916128fc835190565b908192612907606090565b8060019182936060860194612930865173ffffffffffffffffffffffffffffffffffffffff1690565b3f6129416114eb6101ca6007610844565b14612cd7575b612ca2575b82519687916000986129606114eb8b610818565b1115612c545750506129726006610844565b61297e6114eb89610818565b11612c0a575b83805b612b7e575b505050505b60e083019061299f82515190565b90816129ad6114eb88610818565b11612ac9575b5050506119ed612a51612a56612a51612a71946129ec60808801996119a58b5173ffffffffffffffffffffffffffffffffffffffff1690565b61198b612a0d825173ffffffffffffffffffffffffffffffffffffffff1690565b612a1630611187565b98612a3860a082015173ffffffffffffffffffffffffffffffffffffffff1690565b9a81019a6040612a468d5190565b92019a6112398c5190565b955190565b955173ffffffffffffffffffffffffffffffffffffffff1690565b94612ac4612ab1612aab612aa57f09c7d1ab159dbdc16054d51213cf8ab76b507ff896aca64379b18e54ce7959ef96611187565b96610818565b96611187565b96612abb60405190565b938493846128cf565b0390a4565b9081805b612ad8575b506129b3565b15612b69575b612ae88691612856565b91828960c08801612b01612afd8483516128b0565b5190565b612b0d6114eb8c610818565b11612b1e575b505050919082612acd565b61198b612b59612b52612b44869e956119f26119ed612afd612b619a6119a599516128b0565b612b4c61280d565b90612847565b8094611307565b9b88516128b0565b388981612b13565b612b7286610818565b8111612ade5780612ad2565b15612bf5575b612b8e8791612856565b9081612b9d612afd82866128b0565b612ba96114eb8b610818565b11612bb6575b5084612987565b98612bf0612bcc8792611ae2612afd8e896128b0565b9a6119a5612bea612afd612be361198b858c6128b0565b93896128b0565b91611187565b612baf565b612bfe87610818565b8111612b84578061298c565b612c4f612c2f612c28612b44612c1e8d5190565b6119f26006610844565b809a611307565b986119a560035473ffffffffffffffffffffffffffffffffffffffff1690565b612984565b612b44919950612c9d9450612c7d9350612c769250612c718b5190565b611019565b8097611307565b956119a560035473ffffffffffffffffffffffffffffffffffffffff1690565b612991565b915050612cd0612cc6845173ffffffffffffffffffffffffffffffffffffffff1690565b85518951916131c7565b909161294c565b506000807f00000000000000000000000000000000000000000000000000000000000000006004612d568a6114af8b612d3c612d3688612d30637abab711945173ffffffffffffffffffffffffffffffffffffffff1690565b95015190565b91611314565b92612d4660405190565b95869460208601908152016127ba565b82602082019151925af150612d81612d6c6113af565b6020612d76825190565b8183010191016127f9565b612947565b60006101b492612d9e612d998394611187565b611187565b90612da860405190565b90818003925af16114d06113af565b6101b490612de6612ddd60005473ffffffffffffffffffffffffffffffffffffffff1690565b6111f1336112bf565b6101b4906003611690565b6101b490612db7565b906101b49291612e22612ddd60005473ffffffffffffffffffffffffffffffffffffffff1690565b6101b49291612e35612e3c926004610cec565b6005610cec565b6006610cec565b906101b49291612dfa565b612e56610e3e565b906000825260208080808080808089016000815201600081520160008152016000815201600081520160608152016060905250565b6101ca612e4e565b6111a26101ca91612ea2612e8b565b506008610825565b612eb76301ffc9a7611314565b7fffffffff00000000000000000000000000000000000000000000000000000000821614908115612f29575b8115612eed575090565b9050612f25612eff63150b7a02611314565b917fffffffff000000000000000000000000000000000000000000000000000000001690565b1490565b9050612f3863f23a6e61611314565b7fffffffff0000000000000000000000000000000000000000000000000000000082161490612ee3565b612f84612ddd60005473ffffffffffffffffffffffffffffffffffffffff1690565b6101b4612fa2565b6102426101ca6101ca9290565b6101ca90612f8c565b6101b4612faf6000612f99565b613049565b6101b4612f62565b6101b490612fe2612ddd60005473ffffffffffffffffffffffffffffffffffffffff1690565b6101b490612faf612ff66102426000612f99565b73ffffffffffffffffffffffffffffffffffffffff83161415610f86565b6101b490612fbc565b73ffffffffffffffffffffffffffffffffffffffff90911681526040810192916101b49160209061090e565b60005473ffffffffffffffffffffffffffffffffffffffff169061306e816000611690565b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09161127a61309c60405190565b9283928361301d565b60006101ca916130b3600090565b5001610844565b6101b4906116c260006130cd6001610818565b92019161071683610844565b909291926130e961040a826103e2565b938185526020808601920283019281841161017757915b83831061310d5750505050565b6020809161311b8486611fed565b815201920191613100565b9080601f830112156101775781516101ca926020016130d9565b91909160408184031261017757805167ffffffffffffffff8111610177578361316a918301613126565b92602082015167ffffffffffffffff8111610177576101ca9201611fd3565b73ffffffffffffffffffffffffffffffffffffffff90911681526060810193926101b492909160409161274a906128e6565b6040513d6000823e3d90fd5b60009193926131d4606090565b5061320d836131e230611187565b637fea43b86132186131f6620f4240610818565b9561320060405190565b9a8b988997889560e01b90565b855260048501613189565b0393f19182600091829461328b575b506114eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f526f79616c7479206c6f6f6b7570206661696c656400000000000000000000006044820152606490fd5b9093506132a9913d8091833e6132a18183610389565b810190613140565b9238613227565b90602082820312610177576101ca91611fed565b9081526040810192916101b49160200152565b9190604083820312610177576101ca906132f18185611fed565b93602001611f79565b6133076101ca6101ca9290565b63ffffffff1690565b61ffff81166101a0565b905051906101b482613310565b9190916040818403126101775761335c61334160406103ce565b93600061334e8285611fed565b90860152602080930161331a565b90830152565b9092919261337261040a826103e2565b93818552604060208601920283019281841161017757915b8383106133975750505050565b60206040916133a68486613327565b81520192019161338a565b9080601f830112156101775781516101ca92602001613362565b9060208282031261017757815167ffffffffffffffff8111610177576101ca92016133b1565b906113aa61040a836103e2565b369037565b906101b4613419613413846133f1565b936103e2565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001602084016133fe565b6101ca6101ca6101ca9261ffff1690565b1561345c57565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642073706c6974000000000000000000000000000000000000006044820152606490fd5b90602082820312610177576101ca91611f79565b6bffffffffffffffffffffffff81166101a0565b905051906101b4826134cf565b9190916040818403126101775761335c61350a60406103ce565b9360006135178285611fed565b9086015260208093016134e3565b9092919261353561040a826103e2565b93818552604060208601920283019281841161017757915b83831061355a5750505050565b602060409161356984866134f0565b81520192019161354d565b9080601f830112156101775781516101ca92602001613525565b9060208282031261017757815167ffffffffffffffff8111610177576101ca9201613574565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146110375760010190565b6101ca6101ca6101ca926bffffffffffffffffffffffff1690565b9060208282031261017757815167ffffffffffffffff8111610177576101ca9201613126565b9060208282031261017757815167ffffffffffffffff8111610177576101ca9201611fd3565b60609392849291906136996020613681612d997f0000000000000000000000000000000000000000000000000000000000000000611187565b63de5488af9061369060405190565b93849260e01b90565b825273ffffffffffffffffffffffffffffffffffffffff8616600483015260249082905afa8015613b06576136d69160009161416a575b50611187565b906136e082611187565b9163d6a1919a6136f96136f260405190565b9160e01b90565b81526000818061370d868a600484016132c4565b038183885af180600092839261414c575b50613e3f575050632a55205a6137366136f260405190565b81526040818061374a868a600484016132c4565b0381875afa806000928392614119575b50613e8857505063bb3bafd66137726136f260405190565b815260048101869052600081602481875afa806000928392613e6a575b50613e3f5750506137b46102427341a322b28d0ff354040e2cbc676f0320d8c8850d90565b73ffffffffffffffffffffffffffffffffffffffff8516148015613e0c575b613cb5575b63cad96cca6137e96136f260405190565b815260048101869052600081602481875afa60009181613c92575b50613b26575063b9c4d9fb61381860405190565b6138228260e01b90565b815260048101879052600081602481885afa60009181613b0b575b50613a4d575b505063d5a06d4c6138566136f260405190565b815260048101869052600081602481875afa806000928392613a2f575b506139b957505063f662207461388b6136f260405190565b81526000818061389f8989600484016127ba565b0381875afa806000928392613a11575b506139b9575050639ca7dc7a6138c76136f260405190565b8152600081806138db8989600484016127ba565b0381875afa8060009283926139f3575b506139b9575050600093929161320d915061391b63fbda03ab9161390e60405190565b9788968795869560e01b90565b03915afa9081600091829361399c575b506139365750509190565b8051919450915061394b6114eb6101ca865190565b03613954579190565b6139606119ed84925190565b90611b5361396d60405190565b9283927fab8b67c6000000000000000000000000000000000000000000000000000000008452600484016132c4565b9092506139b2913d8091833e6132a18183610389565b913861392b565b9650975050925050506139ca845190565b6139d86114eb6101ca855190565b036139e757906101ca91614188565b506139606119ed845190565b9092613a0992503d8091833e6132a18183610389565b9091386138eb565b9092613a2792503d8091833e6132a18183610389565b9091386138af565b9092613a4592503d8091833e6132a18183610389565b909138613873565b50613a5a6136f260405190565b815260048101869052600081602481875afa908115613b0657600091613ae5575b50630ebd4c7f613a8d6136f260405190565b815260048101879052600081602481885afa60009181613ac2575b5015600003613843579650975050925050506139ca845190565b613ade91923d8091833e613ad68183610389565b810190613622565b9038613aa8565b613b00913d8091833e613af88183610389565b8101906135fc565b38613a7b565b6131bb565b613b1f91923d8091833e613af88183610389565b903861383d565b9750509350505050613b3e613b39845190565b613403565b90613b4a613b39855190565b936000926000613b5981610818565b945b613b666101ca855190565b861015613c3a57613c2e613c3491613c1b613c0e613c03613bfd613bf86020613be48e613bde8d8f838f613bbd90613ba183613bc3956128b0565b51015173ffffffffffffffffffffffffffffffffffffffff1690565b926128b0565b9073ffffffffffffffffffffffffffffffffffffffff169052565b8d6128b0565b5101516bffffffffffffffffffffffff1690565b6135e1565b8a611019565b612b4c612710610818565b613c188a8d6128b0565b52565b613c28612afd898c6128b0565b906120c4565b956135b4565b94613b5b565b9391945050613c47915090565b8111613c5257509190565b611b5390613c5f60405190565b9182917f3728b83d0000000000000000000000000000000000000000000000000000000083526004830190815260200190565b613cae91923d8091833e613ca68183610389565b81019061358e565b9038613804565b613cd3612d997317b0c8564e53f22364a6c8de6f7ca5ce9bea4e5d81565b63b85ed7e490613cec613ce560405190565b9260e01b90565b825260208280613d008a8a600484016127ba565b0381845afa60009281613ddc575b50613d1b575b50506137d8565b6020613d309163860110f59061369060405190565b82528180613d43898d8d60048501613189565b03915afa60009181613dac575b5015600003613d14579650975050505050506114eb613d6f6001610818565b91613c18613da6613d88613d8286613403565b95613403565b96613da1600091613bc3613d9b84610818565b896128b0565b610818565b866128b0565b613dce91925060203d8111613dd5575b613dc68183610389565b8101906134bb565b9038613d50565b503d613dbc565b613dfe91935060203d8111613e05575b613df68183610389565b8101906132b0565b9138613d0e565b503d613dec565b5073b932a70a57673d89f4acffbe830e8ed7f75fb9e073ffffffffffffffffffffffffffffffffffffffff8516146137d3565b95509750509150506101ca9250613e65613e57865190565b6111f16114eb6101ca865190565b614188565b9092613e8092503d8091833e6132a18183610389565b90913861378f565b9593965097509250831161410c5760009384918291883b613eb5613eab856132fa565b9163ffffffff1690565b11614029575b613eec9450613ede63fd90e897613ed160405190565b9687948593849360e01b90565b835260048301526024820190565b03915afa849281614005575b50613f3e5750506114eb90613c18613da6613f136001610818565b94613da1613f32613f2c613f2689613403565b98613403565b99611187565b613bc3613d9b84610818565b9290939450613f4b845190565b93613f5585613403565b90613f5f86613403565b96855b88885b881015613fe957613fda88613f659361233c613fe194613c18613fd2613c038e612c718f8f8f91613fc4602092613bc38e613bbd613fa682613fcd996128b0565b519586015173ffffffffffffffffffffffffffffffffffffffff1690565b015161ffff1690565b613444565b9485926128b0565b9760010190565b969050613f62565b5093509550509250613ffe6114eb6114eb9390565b1115613455565b6140229193503d8087833e61401a8183610389565b8101906133cb565b9138613ef8565b9161404d9061403e612d998b97949697611187565b63d78d610b9061369060405190565b825260049082905afa8791816140f0575b50158714614070575092918591613ebb565b95975050505050614082613b39835190565b9361408e613b39845190565b9461409882610818565b936140a1815190565b95855b88885b881015613fe957613fda886140a79361233c6140e894613c18613fd2613c038e612c718f8f8f91613fc4602092613bc38e613bbd613fa682613fcd996128b0565b9690506140a4565b6141059192503d808a833e61401a8183610389565b903861405e565b611b5383613c5f60405190565b90925061413d915060403d8111614145575b6141358183610389565b8101906132d7565b90913861375a565b503d61412b565b909261416292503d8091833e6132a18183610389565b90913861371e565b614182915060203d8111613e0557613df68183610389565b386136d0565b9190614195613b39825190565b926000916141a36000610818565b925b6141b06101ca835190565b8410156141fd576141f16141f7916141e46141da613c036141d4612afd8a896128b0565b88611019565b613c18888b6128b0565b613c28612afd878a6128b0565b936135b4565b926141a5565b93949392506142099050565b8111613c5257509056000000000000000000000000ad2184fb5dbcfc05d8f056542fb25b04fa32a95d000000000000000000000000167a296135c0067903d4c099806405f6c316442e618d4f1f0a3a895f9e0af7fba63dbbfdb28ec1fb0650450b40f7fa3df9877487
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c806301ffc9a71461017257806311a003271461016d578063150b7a021461016857806317a288df146101635780631efeff841461015e5780632b1708b0146101595780632ede65df1461015457806332689eb81461014f5780633596188d1461014a5780635333a0a4146101455780635e9e78d014610140578063715018a61461013b57806374268ff2146101365780637fea43b8146101315780638a72ea6a1461012c5780638b4c042a146101275780638da5cb5b14610122578063a85c38ef1461011d578063c402b96514610118578063e74b981b14610113578063f23a6e611461010e5763f2fde38b0361017757610ca6565b610c87565b610b83565b610b58565b610ae5565b610974565b61095b565b61092a565b6107e9565b6106e5565b6106cd565b6106a9565b61068d565b610611565b6105fd565b6105bd565b6105a9565b610560565b610524565b610308565b610225565b6101cd565b600080fd5b7fffffffff0000000000000000000000000000000000000000000000000000000081165b0361017757565b905035906101b48261017c565b565b90602082820312610177576101ca916101a7565b90565b34610177576101fa6101e86101e33660046101b6565b612eaa565b60405191829182901515815260200190565b0390f35b806101a0565b905035906101b4826101fe565b90602082820312610177576101ca91610204565b346101775761023d610238366004610211565b611190565b604051005b73ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff81166101a0565b905035906101b48261025b565b909182601f830112156101775781359167ffffffffffffffff831161017757602001926001830284011161017757565b90608082820312610177576102c98183610277565b926102d78260208501610277565b926102e58360408301610204565b92606082013567ffffffffffffffff8111610177576103049201610284565b9091565b34610177576101fa61032761031e3660046102b4565b93929092612585565b604051918291827fffffffff00000000000000000000000000000000000000000000000000000000909116815260200190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810190811067ffffffffffffffff8211176103c957604052565b61035a565b906101b46103db60405190565b9283610389565b67ffffffffffffffff81116103c95760208091020190565b9092919261040f61040a826103e2565b6103ce565b938185526020808601920283019281841161017757915b8383106104335750505050565b602080916104418486610204565b815201920191610426565b9080601f83011215610177578160206101ca933591016103fa565b9092919261047761040a826103e2565b938185526020808601920283019281841161017757915b83831061049b5750505050565b602080916104a98486610277565b81520192019161048e565b9080601f83011215610177578160206101ca93359101610467565b91606083830312610177576104e48284610204565b92602081013567ffffffffffffffff8111610177578361050591830161044c565b92604082013567ffffffffffffffff8111610177576101ca92016104b4565b346101775761023d6105373660046104cf565b9161160c565b9190604083820312610177576101ca906105578185610204565b93602001610204565b346101775761023d61057336600461053d565b906113ce565b9091606082840312610177576101ca6105928484610204565b936105a08160208601610204565b93604001610204565b61023d6105b7366004610579565b916119fe565b346101775761023d6105d0366004610579565b91610d07565b9091606082840312610177576101ca6105ef8484610204565b936105a08160208601610277565b61023d61060b3660046105d6565b91611df8565b346101775761023d610624366004610579565b91612e43565b906080828203126101775761063f8183610204565b9261064d8260208501610204565b92604081013567ffffffffffffffff8111610177578361066e91830161044c565b92606082013567ffffffffffffffff8111610177576101ca92016104b4565b346101775761023d6106a036600461062a565b92919091611c19565b346101775761023d6106bc36600461053d565b9061127f565b600091031261017757565b34610177576106dd3660046106c2565b61023d612fb4565b346101775761023d6106f8366004610211565b61190e565b9091606082840312610177576101ca6105928484610277565b0190565b9061073a610733610729845190565b8084529260200190565b9260200190565b9060005b81811061074b5750505090565b90919261077e610777600192865173ffffffffffffffffffffffffffffffffffffffff16815260200190565b9460200190565b92910161073e565b90610795610733610729845190565b9060005b8181106107a65750505090565b9091926107bc6107776001928651815260200190565b929101610799565b60408082526101ca9391926107db9184019061071a565b916020818403910152610786565b34610177576108026107fc3660046106fd565b91613648565b906101fa61080f60405190565b928392836107c4565b6101ca6101ca6101ca9290565b9061082f90610818565b600052602052604060002090565b6101ca9081565b6101ca905461083d565b610859906009610825565b61086281610844565b9161086f60018301610844565b9161087c60028201610844565b916101ca60046108a3600385015473ffffffffffffffffffffffffffffffffffffffff1690565b93015473ffffffffffffffffffffffffffffffffffffffff1690565b909594926101b4946108f161090e926108ea6080966108e360a088019c6000890152565b6020870152565b6040850152565b73ffffffffffffffffffffffffffffffffffffffff166060830152565b019073ffffffffffffffffffffffffffffffffffffffff169052565b34610177576101fa610945610940366004610211565b61084e565b9161095295939560405190565b958695866108bf565b346101775761023d61096e366004610579565b91611b57565b34610177576109843660046106c2565b6101fa6109a660005473ffffffffffffffffffffffffffffffffffffffff1690565b6040519182918273ffffffffffffffffffffffffffffffffffffffff909116815260200190565b906109dc610733610729845190565b9060005b8181106109ed5750505090565b909192610a19610777600192865173ffffffffffffffffffffffffffffffffffffffff16815260200190565b9291016109e0565b805182526101ca9160e0610ac36101008301610a4260208601516020860152565b610a5160408601516040860152565b60608581015173ffffffffffffffffffffffffffffffffffffffff169085015260808581015173ffffffffffffffffffffffffffffffffffffffff169085015260a08581015173ffffffffffffffffffffffffffffffffffffffff169085015260c085015184820360c0860152610786565b9201519060e08184039101526109cd565b60208082526101ca92910190610a21565b34610177576101fa610b00610afb366004610211565b612e93565b60405191829182610ad4565b919060a08382031261017757610b228184610277565b92610b308260208301610204565b926101ca610b418460408501610204565b93610b4f8160608601610277565b93608001610204565b61023d610b66366004610b0c565b93929092611741565b90602082820312610177576101ca91610277565b346101775761023d610b96366004610b6f565b612df1565b67ffffffffffffffff81116103c957602090601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b90826000939282370152565b90929192610bf261040a82610b9b565b93818552602085019082840111610177576101b492610bd6565b9080601f83011215610177578160206101ca93359101610be2565b91909160a08184031261017757610c3e8382610277565b92610c4c8160208401610277565b92610c5a8260408501610204565b92610c688360608301610204565b92608082013567ffffffffffffffff8111610177576101ca9201610c0c565b34610177576101fa610327610c9d366004610c27565b939290926120d1565b346101775761023d610cb9366004610b6f565b613014565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905b9181191691161790565b90610cfc6101ca610d0392610818565b8254610cbe565b9055565b610d216101b493610d1a600193826113ce565b6008610825565b01610cec565b90610d42610d36610729845490565b92600052602060002090565b9060005b818110610d535750505090565b909192610d77610d70600192610d6887610844565b815260200190565b9460010190565b929101610d46565b906101ca91610d27565b906101b4610da392610d9a60405190565b93848092610d7f565b0383610389565b90610db9610d36610729845490565b9060005b818110610dca5750505090565b909192610e12610d70600192610df4875473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16815260200190565b929101610dbd565b906101ca91610daa565b906101b4610da392610e3560405190565b93848092610e1a565b6101ca6101006103ce565b906101b4610f766007610e5a610e3e565b94610e6b610e6782610844565b8752565b610e81610e7a60018301610844565b6020880152565b610e97610e9060028301610844565b6040880152565b610ed8610ebb600383015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff166060880152565b610f19610efc600483015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff166080880152565b610f5a610f3d600583015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1660a0880152565b610f70610f6960068301610d89565b60c0880152565b01610e24565b60e0840152565b6101ca90610e49565b1561017757565b91906008610ce2910291610fc07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841b90565b921b90565b9190610fd66101ca610d0393610818565b908354610f8d565b6101b491600091610fc5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9190611024565b9290565b9180830292818404149015171561103757565b610fea565b818110611047575050565b806110556000600193610fde565b0161103c565b909182811061106957505050565b6101b4929061107790610d36565b908101910161103c565b906801000000000000000081116103c9578161109e6101b4935490565b9082815561105b565b60006101b491611081565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b906000036110f2576101b4906110a7565b6110b2565b600060076101b49261110b83808301610fde565b6111188360018301610fde565b6111258360028301610fde565b82600382015582600482015582600582015561114483600683016110e1565b016110e1565b906000036110f2576101b4906110f7565b6102426101ca6101ca9273ffffffffffffffffffffffffffffffffffffffff1690565b6101ca9061115b565b6101ca9061117e565b61123f60086111a76111a28483610825565b610f7d565b61120160006111fc8633956111f76111d961024260a089015173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff89165b14610f86565b610825565b61114a565b606081015173ffffffffffffffffffffffffffffffffffffffff169161122630611187565b6112396040611233855190565b94015190565b9361274e565b61127a7f91635156bba825be2f9a200b140420e4bee0d251f7d43bf956e63f74960030e09161126d60405190565b9182918290815260200190565b0390a1565b906112d99060016112946101ca856008610825565b610d21336111f16112bf610242600586015473ffffffffffffffffffffffffffffffffffffffff1690565b9173ffffffffffffffffffffffffffffffffffffffff1690565b61127a7fb8b459bc0688c37baf5f735d17f1711684bc14ab7db116f88bc18bf409b9309a9161126d60405190565b9190820391821161103757565b6113276113216101ca9290565b60e01b90565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b73ffffffffffffffffffffffffffffffffffffffff9182168152911660208201526101ca9260a082019261138b9190611384906108ea565b6060830152565b60808183039101526000815260200190565b906113aa61040a83610b9b565b918252565b3d156113c9576113be3d61139d565b903d6000602084013e565b606090565b80916114db6008916114d66000806113e96101ca8888610825565b60046114be3392611433611417610242600584015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff86166111f1565b6114af60028201986114566114508261144b8d610844565b611307565b8b610cec565b600383015473ffffffffffffffffffffffffffffffffffffffff169563f242432a9061149561148f8a61148830611187565b9701610844565b92611314565b9461149f60405190565b978896602088019081520161134c565b60208201810382520382610389565b82602082019151925af16114d06113af565b50610f86565b610844565b906000916114ef6114eb84610818565b9190565b036115015761123f926111fc91610825565b50505061127a7fb8b459bc0688c37baf5f735d17f1711684bc14ab7db116f88bc18bf409b9309a9161126d60405190565b81519167ffffffffffffffff83116103c95761155d610d366001926115578686611081565b60200190565b92049160005b8381106115705750505050565b60019060206115806101ca865190565b9401938184015501611563565b906101b491611532565b81519167ffffffffffffffff83116103c9576115bc610d366001926115578686611081565b92049160005b8381106115cf5750505050565b60019060206115f56101ca865173ffffffffffffffffffffffffffffffffffffffff1690565b94019381840155016115c2565b906101b491611597565b916007611664846112d9946111f733916116526008936111f16112bf61024260056116378a8a610825565b015473ffffffffffffffffffffffffffffffffffffffff1690565b600661165e8585610825565b0161158d565b01611602565b6101ca60a06103ce565b9073ffffffffffffffffffffffffffffffffffffffff90610ce2565b906116a06101ca610d0392611187565b8254611674565b6101b49190611714906080906004906116c8816116c2875190565b90610cec565b6116da600182016116c2602088015190565b6116ec600282016116c2604088015190565b61171a60038201611714606088015173ffffffffffffffffffffffffffffffffffffffff1690565b90611690565b0192015173ffffffffffffffffffffffffffffffffffffffff1690565b906101b4916116a7565b6117fc94936117c16117de926117a46117f79661179d61175f600290565b996117698b6130ba565b6117966000996117788b610818565b850361182a5761178883346111f1565b61179061166a565b9a8b0152565b6020890152565b6040870152565b73ffffffffffffffffffffffffffffffffffffffff166060850152565b73ffffffffffffffffffffffffffffffffffffffff166080830152565b6117f260096117ec856130a5565b90610825565b611737565b6130a5565b61127a7f682fd9923da5632e7c7702dabcfa626195d5f444833bc25f94e418e258e791869161126d60405190565b61183e346111f16114eb6101ca8988611019565b611788565b906101b46118a3600461185461166a565b94611861610e6782610844565b611870610e7a60018301610844565b61187f610e9060028301610844565b611637610ebb600383015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff166080840152565b6101ca90611843565b6000906004906118d98382610fde565b6118e68360018301610fde565b6118f38360028301610fde565b8260038201550155565b906000036110f2576101b4906118c9565b6119aa60096119a56119286119238584610825565b6118c0565b61198b60408201611937815190565b90876000926119486114eb85610818565b036119d85760208501516119869250965b6111f76080339701966111f16112bf6102428a5173ffffffffffffffffffffffffffffffffffffffff1690565b6118fd565b5173ffffffffffffffffffffffffffffffffffffffff1690565b612d86565b61127a7f88686b85d6f2c3ab9a04e4f15a22fcfa025ffd97226dcf0a67cdf682def556769161126d60405190565b6119f8611986926119f26119ed602089015190565b915190565b90611019565b96611959565b9190611a8691611a81611a156101ca866009610825565b91611a41336111f16112bf610242600488015473ffffffffffffffffffffffffffffffffffffffff1690565b60016002840193611a5185610844565b611a5e6114eb6000610818565b03611ab457610d21346111f16114eb6101ca611a7b878701610844565b88611307565b610cec565b61127a7f7eff4a127d11f41398f54211d23467816d498336249c9103adb206d679f0e4829161126d60405190565b611ae8346111f16114eb6101ca611acb8b89611019565b611ae2611ad9898901610844565b6119f28d610844565b90611307565b610d21565b15611af457565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f68777900000000000000000000000000000000000000000000000000000000006044820152606490fd5b0390fd5b91611a8691611b6a6101ca856009610825565b913391611bb1611b94610242600487015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff851614611aed565b611bbb6000610818565b8103611bde5750806001611bd76119a59361144b838801610844565b9401610cec565b9290600182611ae8611bf4836119a59601610844565b96611c13611c0960028501996119f28b610844565b611ae28388611019565b97610cec565b919290926008611c2c6111a28583610825565b906009611c3c6119238883610825565b96611c5e60a085015173ffffffffffffffffffffffffffffffffffffffff1690565b3393908890611c6c866112bf565b1480611ddd575b80611d89575b611c8290610f86565b611c8b91610825565b6000611c969161114a565b611c9f91610825565b6000611caa916118fd565b815195611cb8602082015190565b60609093015160009073ffffffffffffffffffffffffffffffffffffffff1660809092015173ffffffffffffffffffffffffffffffffffffffff1693611cfc610e3e565b98611d0790838b0152565b6020890152611d1590610818565b604088015273ffffffffffffffffffffffffffffffffffffffff16606087015273ffffffffffffffffffffffffffffffffffffffff16608086015273ffffffffffffffffffffffffffffffffffffffff1660a085015260c084015260e0830152611d7f6005610844565b906101b4926128ed565b50611c828a611dd56112bf6102426060611db9818d015173ffffffffffffffffffffffffffffffffffffffff1690565b94015173ffffffffffffffffffffffffffffffffffffffff1690565b149050611c79565b5089611df26114eb6101ca60006112338b5190565b14611c73565b90916101ca92600890611e0e6111a28584610825565b91843491611e1d602086015190565b90611e48611e4260009a8b94611e3286610818565b8b03611f72576119f26001610818565b856111f1565b611e618761144b6002611e5b8786610825565b01610844565b611e6d6114eb84610818565b03611f4e57611e7f926111fc91610825565b8583015193611ea5606085015173ffffffffffffffffffffffffffffffffffffffff1690565b90611ec7608086015173ffffffffffffffffffffffffffffffffffffffff1690565b9260c08601519560e0015196611edb610e3e565b998a01526020890152604088015273ffffffffffffffffffffffffffffffffffffffff16606087015273ffffffffffffffffffffffffffffffffffffffff16608086015273ffffffffffffffffffffffffffffffffffffffff1660a085015260c084015260e0830152611d7f6004610844565b60029150611f6d92611f5f91610825565b016116c28661144b83610844565b611e7f565b8a90611019565b905051906101b4826101fe565b90929192611f9661040a826103e2565b938185526020808601920283019281841161017757915b838310611fba5750505050565b60208091611fc88486611f79565b815201920191611fad565b9080601f830112156101775781516101ca92602001611f86565b905051906101b48261025b565b9092919261200a61040a826103e2565b938185526020808601920283019281841161017757915b83831061202e5750505050565b6020809161203c8486611fed565b815201920191612021565b9080601f830112156101775781516101ca92602001611ffa565b90608082820312610177576120768183611f79565b926120848260208501611f79565b92604081015167ffffffffffffffff811161017757836120a5918301611fd3565b92606082015167ffffffffffffffff8111610177576101ca9201612047565b9190820180921161103757565b939092906120ee9060206120e3825190565b818301019101612061565b9492959160009491949761210189610818565b82036122895750506009906121196119238884610825565b878961213c606084015173ffffffffffffffffffffffffffffffffffffffff1690565b339590612148876112bf565b1480612272575b61215890610f86565b61216b8561144b6002611e5b8786610825565b6121776114eb84610818565b0361224e576121899261198691610825565b81612195602083015190565b9061219f91611019565b60809091015173ffffffffffffffffffffffffffffffffffffffff16946121c4610e3e565b998a01526020890152604088015273ffffffffffffffffffffffffffffffffffffffff16606087015273ffffffffffffffffffffffffffffffffffffffff16608086015273ffffffffffffffffffffffffffffffffffffffff1660a085015260c084015260e08301526122376005610844565b90612241926128ed565b6101ca63f23a6e61611314565b6002915061226d9261225f91610825565b016116c28461144b83610844565b612189565b506121586122808386015190565b8914905061214f565b909495969761229b8195949395610818565b89036122b157506122ac97506124ac565b612241565b6123419750600195965061232b91949250610d21936122d46101ca8b6008610825565b956123166112bf6122fc60058a015473ffffffffffffffffffffffffffffffffffffffff1690565b9273ffffffffffffffffffffffffffffffffffffffff1690565b149182612393575b82612377575b5050610f86565b6116c2600284019161233c83610844565b6120c4565b61236f7fb8b459bc0688c37baf5f735d17f1711684bc14ab7db116f88bc18bf409b9309a9161126d60405190565b0390a1612241565b61238b9192506110206114eb918801610844565b143880612324565b91506123b6600387015473ffffffffffffffffffffffffffffffffffffffff1690565b6123bf336112bf565b149161231e565b6101b4919061249c9060e0906007906123e1816116c2875190565b6123f3600182016116c2602088015190565b612405600282016116c2604088015190565b61242d60038201611714606088015173ffffffffffffffffffffffffffffffffffffffff1690565b61245560048201611714608088015173ffffffffffffffffffffffffffffffffffffffff1690565b61247d6005820161171460a088015173ffffffffffffffffffffffffffffffffffffffff1690565b6124956006820161248f60c088015190565b9061158d565b0192015190565b90611602565b906101b4916123c6565b919492959360016124bc816130ba565b6124c5906130a5565b9633916124d0610e3e565b9788526020880152604087015273ffffffffffffffffffffffffffffffffffffffff16606086015273ffffffffffffffffffffffffffffffffffffffff16608085015273ffffffffffffffffffffffffffffffffffffffff1660a084015260c083015260e0820152612543826008610825565b9061254d916124a2565b7f7e82078c35b6665b9d320ebeaa6c266960fad5b802c5558cf7df60c4769af95b9061257860405190565b908152806020810161127a565b9261259d919294612594600090565b5081019061062a565b9491926000949194906125af82610818565b81036125d75750906125c46125ca9792610818565b926124ac565b6101ca63150b7a02611314565b95949350915060096125ec6119238783610825565b928061260f606086015173ffffffffffffffffffffffffffffffffffffffff1690565b339390899061261d866112bf565b14806126fc575b61262d90610f86565b61263691610825565b90612640916118fd565b602084015160809094015173ffffffffffffffffffffffffffffffffffffffff169361266a610e3e565b9861267590838b0152565b602089015261268390610818565b604088015273ffffffffffffffffffffffffffffffffffffffff16606087015273ffffffffffffffffffffffffffffffffffffffff16608086015273ffffffffffffffffffffffffffffffffffffffff1660a085015260c084015260e08301526126ed6005610844565b906126f7926128ed565b6125ca565b5061262d8b6127116114eb611020878c015190565b149050612624565b73ffffffffffffffffffffffffffffffffffffffff9182168152911660208201526060810192916101b49160400152565b0152565b906101b4949293600491612760600090565b50600095869561276f87610818565b81036127a557506114be926114af9161278b6342842e0e611314565b9361279560405190565b9687956020870190815201612719565b6114be936114af9261149563f242432a611314565b73ffffffffffffffffffffffffffffffffffffffff90911681526040810192916101b49160200152565b8015156101a0565b905051906101b4826127e4565b90602082820312610177576101ca916127ec565b6101ca612710610818565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8115612851570490565b612818565b8015611037577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906128b9825190565b8110156128ca576020809102010190565b612881565b9081526060810193926101b492909160409161274a905b6020830152565b909160208201916128fc835190565b908192612907606090565b8060019182936060860194612930865173ffffffffffffffffffffffffffffffffffffffff1690565b3f6129416114eb6101ca6007610844565b14612cd7575b612ca2575b82519687916000986129606114eb8b610818565b1115612c545750506129726006610844565b61297e6114eb89610818565b11612c0a575b83805b612b7e575b505050505b60e083019061299f82515190565b90816129ad6114eb88610818565b11612ac9575b5050506119ed612a51612a56612a51612a71946129ec60808801996119a58b5173ffffffffffffffffffffffffffffffffffffffff1690565b61198b612a0d825173ffffffffffffffffffffffffffffffffffffffff1690565b612a1630611187565b98612a3860a082015173ffffffffffffffffffffffffffffffffffffffff1690565b9a81019a6040612a468d5190565b92019a6112398c5190565b955190565b955173ffffffffffffffffffffffffffffffffffffffff1690565b94612ac4612ab1612aab612aa57f09c7d1ab159dbdc16054d51213cf8ab76b507ff896aca64379b18e54ce7959ef96611187565b96610818565b96611187565b96612abb60405190565b938493846128cf565b0390a4565b9081805b612ad8575b506129b3565b15612b69575b612ae88691612856565b91828960c08801612b01612afd8483516128b0565b5190565b612b0d6114eb8c610818565b11612b1e575b505050919082612acd565b61198b612b59612b52612b44869e956119f26119ed612afd612b619a6119a599516128b0565b612b4c61280d565b90612847565b8094611307565b9b88516128b0565b388981612b13565b612b7286610818565b8111612ade5780612ad2565b15612bf5575b612b8e8791612856565b9081612b9d612afd82866128b0565b612ba96114eb8b610818565b11612bb6575b5084612987565b98612bf0612bcc8792611ae2612afd8e896128b0565b9a6119a5612bea612afd612be361198b858c6128b0565b93896128b0565b91611187565b612baf565b612bfe87610818565b8111612b84578061298c565b612c4f612c2f612c28612b44612c1e8d5190565b6119f26006610844565b809a611307565b986119a560035473ffffffffffffffffffffffffffffffffffffffff1690565b612984565b612b44919950612c9d9450612c7d9350612c769250612c718b5190565b611019565b8097611307565b956119a560035473ffffffffffffffffffffffffffffffffffffffff1690565b612991565b915050612cd0612cc6845173ffffffffffffffffffffffffffffffffffffffff1690565b85518951916131c7565b909161294c565b506000807f000000000000000000000000167a296135c0067903d4c099806405f6c316442e6004612d568a6114af8b612d3c612d3688612d30637abab711945173ffffffffffffffffffffffffffffffffffffffff1690565b95015190565b91611314565b92612d4660405190565b95869460208601908152016127ba565b82602082019151925af150612d81612d6c6113af565b6020612d76825190565b8183010191016127f9565b612947565b60006101b492612d9e612d998394611187565b611187565b90612da860405190565b90818003925af16114d06113af565b6101b490612de6612ddd60005473ffffffffffffffffffffffffffffffffffffffff1690565b6111f1336112bf565b6101b4906003611690565b6101b490612db7565b906101b49291612e22612ddd60005473ffffffffffffffffffffffffffffffffffffffff1690565b6101b49291612e35612e3c926004610cec565b6005610cec565b6006610cec565b906101b49291612dfa565b612e56610e3e565b906000825260208080808080808089016000815201600081520160008152016000815201600081520160608152016060905250565b6101ca612e4e565b6111a26101ca91612ea2612e8b565b506008610825565b612eb76301ffc9a7611314565b7fffffffff00000000000000000000000000000000000000000000000000000000821614908115612f29575b8115612eed575090565b9050612f25612eff63150b7a02611314565b917fffffffff000000000000000000000000000000000000000000000000000000001690565b1490565b9050612f3863f23a6e61611314565b7fffffffff0000000000000000000000000000000000000000000000000000000082161490612ee3565b612f84612ddd60005473ffffffffffffffffffffffffffffffffffffffff1690565b6101b4612fa2565b6102426101ca6101ca9290565b6101ca90612f8c565b6101b4612faf6000612f99565b613049565b6101b4612f62565b6101b490612fe2612ddd60005473ffffffffffffffffffffffffffffffffffffffff1690565b6101b490612faf612ff66102426000612f99565b73ffffffffffffffffffffffffffffffffffffffff83161415610f86565b6101b490612fbc565b73ffffffffffffffffffffffffffffffffffffffff90911681526040810192916101b49160209061090e565b60005473ffffffffffffffffffffffffffffffffffffffff169061306e816000611690565b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09161127a61309c60405190565b9283928361301d565b60006101ca916130b3600090565b5001610844565b6101b4906116c260006130cd6001610818565b92019161071683610844565b909291926130e961040a826103e2565b938185526020808601920283019281841161017757915b83831061310d5750505050565b6020809161311b8486611fed565b815201920191613100565b9080601f830112156101775781516101ca926020016130d9565b91909160408184031261017757805167ffffffffffffffff8111610177578361316a918301613126565b92602082015167ffffffffffffffff8111610177576101ca9201611fd3565b73ffffffffffffffffffffffffffffffffffffffff90911681526060810193926101b492909160409161274a906128e6565b6040513d6000823e3d90fd5b60009193926131d4606090565b5061320d836131e230611187565b637fea43b86132186131f6620f4240610818565b9561320060405190565b9a8b988997889560e01b90565b855260048501613189565b0393f19182600091829461328b575b506114eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f526f79616c7479206c6f6f6b7570206661696c656400000000000000000000006044820152606490fd5b9093506132a9913d8091833e6132a18183610389565b810190613140565b9238613227565b90602082820312610177576101ca91611fed565b9081526040810192916101b49160200152565b9190604083820312610177576101ca906132f18185611fed565b93602001611f79565b6133076101ca6101ca9290565b63ffffffff1690565b61ffff81166101a0565b905051906101b482613310565b9190916040818403126101775761335c61334160406103ce565b93600061334e8285611fed565b90860152602080930161331a565b90830152565b9092919261337261040a826103e2565b93818552604060208601920283019281841161017757915b8383106133975750505050565b60206040916133a68486613327565b81520192019161338a565b9080601f830112156101775781516101ca92602001613362565b9060208282031261017757815167ffffffffffffffff8111610177576101ca92016133b1565b906113aa61040a836103e2565b369037565b906101b4613419613413846133f1565b936103e2565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001602084016133fe565b6101ca6101ca6101ca9261ffff1690565b1561345c57565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642073706c6974000000000000000000000000000000000000006044820152606490fd5b90602082820312610177576101ca91611f79565b6bffffffffffffffffffffffff81166101a0565b905051906101b4826134cf565b9190916040818403126101775761335c61350a60406103ce565b9360006135178285611fed565b9086015260208093016134e3565b9092919261353561040a826103e2565b93818552604060208601920283019281841161017757915b83831061355a5750505050565b602060409161356984866134f0565b81520192019161354d565b9080601f830112156101775781516101ca92602001613525565b9060208282031261017757815167ffffffffffffffff8111610177576101ca9201613574565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146110375760010190565b6101ca6101ca6101ca926bffffffffffffffffffffffff1690565b9060208282031261017757815167ffffffffffffffff8111610177576101ca9201613126565b9060208282031261017757815167ffffffffffffffff8111610177576101ca9201611fd3565b60609392849291906136996020613681612d997f000000000000000000000000ad2184fb5dbcfc05d8f056542fb25b04fa32a95d611187565b63de5488af9061369060405190565b93849260e01b90565b825273ffffffffffffffffffffffffffffffffffffffff8616600483015260249082905afa8015613b06576136d69160009161416a575b50611187565b906136e082611187565b9163d6a1919a6136f96136f260405190565b9160e01b90565b81526000818061370d868a600484016132c4565b038183885af180600092839261414c575b50613e3f575050632a55205a6137366136f260405190565b81526040818061374a868a600484016132c4565b0381875afa806000928392614119575b50613e8857505063bb3bafd66137726136f260405190565b815260048101869052600081602481875afa806000928392613e6a575b50613e3f5750506137b46102427341a322b28d0ff354040e2cbc676f0320d8c8850d90565b73ffffffffffffffffffffffffffffffffffffffff8516148015613e0c575b613cb5575b63cad96cca6137e96136f260405190565b815260048101869052600081602481875afa60009181613c92575b50613b26575063b9c4d9fb61381860405190565b6138228260e01b90565b815260048101879052600081602481885afa60009181613b0b575b50613a4d575b505063d5a06d4c6138566136f260405190565b815260048101869052600081602481875afa806000928392613a2f575b506139b957505063f662207461388b6136f260405190565b81526000818061389f8989600484016127ba565b0381875afa806000928392613a11575b506139b9575050639ca7dc7a6138c76136f260405190565b8152600081806138db8989600484016127ba565b0381875afa8060009283926139f3575b506139b9575050600093929161320d915061391b63fbda03ab9161390e60405190565b9788968795869560e01b90565b03915afa9081600091829361399c575b506139365750509190565b8051919450915061394b6114eb6101ca865190565b03613954579190565b6139606119ed84925190565b90611b5361396d60405190565b9283927fab8b67c6000000000000000000000000000000000000000000000000000000008452600484016132c4565b9092506139b2913d8091833e6132a18183610389565b913861392b565b9650975050925050506139ca845190565b6139d86114eb6101ca855190565b036139e757906101ca91614188565b506139606119ed845190565b9092613a0992503d8091833e6132a18183610389565b9091386138eb565b9092613a2792503d8091833e6132a18183610389565b9091386138af565b9092613a4592503d8091833e6132a18183610389565b909138613873565b50613a5a6136f260405190565b815260048101869052600081602481875afa908115613b0657600091613ae5575b50630ebd4c7f613a8d6136f260405190565b815260048101879052600081602481885afa60009181613ac2575b5015600003613843579650975050925050506139ca845190565b613ade91923d8091833e613ad68183610389565b810190613622565b9038613aa8565b613b00913d8091833e613af88183610389565b8101906135fc565b38613a7b565b6131bb565b613b1f91923d8091833e613af88183610389565b903861383d565b9750509350505050613b3e613b39845190565b613403565b90613b4a613b39855190565b936000926000613b5981610818565b945b613b666101ca855190565b861015613c3a57613c2e613c3491613c1b613c0e613c03613bfd613bf86020613be48e613bde8d8f838f613bbd90613ba183613bc3956128b0565b51015173ffffffffffffffffffffffffffffffffffffffff1690565b926128b0565b9073ffffffffffffffffffffffffffffffffffffffff169052565b8d6128b0565b5101516bffffffffffffffffffffffff1690565b6135e1565b8a611019565b612b4c612710610818565b613c188a8d6128b0565b52565b613c28612afd898c6128b0565b906120c4565b956135b4565b94613b5b565b9391945050613c47915090565b8111613c5257509190565b611b5390613c5f60405190565b9182917f3728b83d0000000000000000000000000000000000000000000000000000000083526004830190815260200190565b613cae91923d8091833e613ca68183610389565b81019061358e565b9038613804565b613cd3612d997317b0c8564e53f22364a6c8de6f7ca5ce9bea4e5d81565b63b85ed7e490613cec613ce560405190565b9260e01b90565b825260208280613d008a8a600484016127ba565b0381845afa60009281613ddc575b50613d1b575b50506137d8565b6020613d309163860110f59061369060405190565b82528180613d43898d8d60048501613189565b03915afa60009181613dac575b5015600003613d14579650975050505050506114eb613d6f6001610818565b91613c18613da6613d88613d8286613403565b95613403565b96613da1600091613bc3613d9b84610818565b896128b0565b610818565b866128b0565b613dce91925060203d8111613dd5575b613dc68183610389565b8101906134bb565b9038613d50565b503d613dbc565b613dfe91935060203d8111613e05575b613df68183610389565b8101906132b0565b9138613d0e565b503d613dec565b5073b932a70a57673d89f4acffbe830e8ed7f75fb9e073ffffffffffffffffffffffffffffffffffffffff8516146137d3565b95509750509150506101ca9250613e65613e57865190565b6111f16114eb6101ca865190565b614188565b9092613e8092503d8091833e6132a18183610389565b90913861378f565b9593965097509250831161410c5760009384918291883b613eb5613eab856132fa565b9163ffffffff1690565b11614029575b613eec9450613ede63fd90e897613ed160405190565b9687948593849360e01b90565b835260048301526024820190565b03915afa849281614005575b50613f3e5750506114eb90613c18613da6613f136001610818565b94613da1613f32613f2c613f2689613403565b98613403565b99611187565b613bc3613d9b84610818565b9290939450613f4b845190565b93613f5585613403565b90613f5f86613403565b96855b88885b881015613fe957613fda88613f659361233c613fe194613c18613fd2613c038e612c718f8f8f91613fc4602092613bc38e613bbd613fa682613fcd996128b0565b519586015173ffffffffffffffffffffffffffffffffffffffff1690565b015161ffff1690565b613444565b9485926128b0565b9760010190565b969050613f62565b5093509550509250613ffe6114eb6114eb9390565b1115613455565b6140229193503d8087833e61401a8183610389565b8101906133cb565b9138613ef8565b9161404d9061403e612d998b97949697611187565b63d78d610b9061369060405190565b825260049082905afa8791816140f0575b50158714614070575092918591613ebb565b95975050505050614082613b39835190565b9361408e613b39845190565b9461409882610818565b936140a1815190565b95855b88885b881015613fe957613fda886140a79361233c6140e894613c18613fd2613c038e612c718f8f8f91613fc4602092613bc38e613bbd613fa682613fcd996128b0565b9690506140a4565b6141059192503d808a833e61401a8183610389565b903861405e565b611b5383613c5f60405190565b90925061413d915060403d8111614145575b6141358183610389565b8101906132d7565b90913861375a565b503d61412b565b909261416292503d8091833e6132a18183610389565b90913861371e565b614182915060203d8111613e0557613df68183610389565b386136d0565b9190614195613b39825190565b926000916141a36000610818565b925b6141b06101ca835190565b8410156141fd576141f16141f7916141e46141da613c036141d4612afd8a896128b0565b88611019565b613c18888b6128b0565b613c28612afd878a6128b0565b936135b4565b926141a5565b93949392506142099050565b8111613c5257509056
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ad2184fb5dbcfc05d8f056542fb25b04fa32a95d000000000000000000000000167a296135c0067903d4c099806405f6c316442e618d4f1f0a3a895f9e0af7fba63dbbfdb28ec1fb0650450b40f7fa3df9877487
-----Decoded View---------------
Arg [0] : _royaltyRegistry (address): 0xaD2184FB5DBcfC05d8f056542fB25b04fa32A95D
Arg [1] : _primaryMarketRegistry (address): 0x167A296135c0067903d4C099806405f6c316442E
Arg [2] : ERC721SovreignV1CodeHash (bytes32): 0x618d4f1f0a3a895f9e0af7fba63dbbfdb28ec1fb0650450b40f7fa3df9877487
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000ad2184fb5dbcfc05d8f056542fb25b04fa32a95d
Arg [1] : 000000000000000000000000167a296135c0067903d4c099806405f6c316442e
Arg [2] : 618d4f1f0a3a895f9e0af7fba63dbbfdb28ec1fb0650450b40f7fa3df9877487
Loading...
Loading
Loading...
Loading
Net Worth in USD
$322.42
Net Worth in ETH
0.149997
Token Allocations
ETH
100.00%
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $2,149.45 | 0.15 | $322.42 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.