Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Transfer Ownersh... | 15028822 | 981 days ago | IN | 0 ETH | 0.00086401 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
InfinityOrderBookComplication
Compiler Version
v0.8.14+commit.80d49f37
Optimization Enabled:
Yes with 99999999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.14; // external imports import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol'; import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; // internal imports import {SignatureChecker} from '../libs/SignatureChecker.sol'; import {OrderTypes} from '../libs/OrderTypes.sol'; import {IComplication} from '../interfaces/IComplication.sol'; /** * @title InfinityOrderBookComplication * @author nneverlander. Twitter @nneverlander * @notice Complication to execute orderbook orders */ contract InfinityOrderBookComplication is IComplication, Ownable { using EnumerableSet for EnumerableSet.AddressSet; uint256 public constant PRECISION = 1e4; // precision for division; similar to bps /// @dev WETH address of the chain being used address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // keccak256('Order(bool isSellOrder,address signer,uint256[] constraints,OrderItem[] nfts,address[] execParams,bytes extraParams)OrderItem(address collection,TokenInfo[] tokens)TokenInfo(uint256 tokenId,uint256 numTokens)') bytes32 public constant ORDER_HASH = 0x7bcfb5a29031e6b8d34ca1a14dd0a1f5cb11b20f755bb2a31ee3c4b143477e4a; // keccak256('OrderItem(address collection,TokenInfo[] tokens)TokenInfo(uint256 tokenId,uint256 numTokens)') bytes32 public constant ORDER_ITEM_HASH = 0xf73f37e9f570369ceaab59cef16249ae1c0ad1afd592d656afac0be6f63b87e0; // keccak256('TokenInfo(uint256 tokenId,uint256 numTokens)') bytes32 public constant TOKEN_INFO_HASH = 0x88f0bd19d14f8b5d22c0605a15d9fffc285ebc8c86fb21139456d305982906f1; /// @dev Used in order signing with EIP-712 bytes32 public immutable DOMAIN_SEPARATOR; /// @dev Storage variable that keeps track of valid currencies used for payment (tokens) EnumerableSet.AddressSet private _currencies; event CurrencyAdded(address currency); event CurrencyRemoved(address currency); constructor() { // Calculate the domain separator DOMAIN_SEPARATOR = keccak256( abi.encode( keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), keccak256('InfinityComplication'), keccak256(bytes('1')), // for versionId = 1 block.chainid, address(this) ) ); // add default currencies _currencies.add(WETH); _currencies.add(address(0)); // ETH } // ======================================================= EXTERNAL FUNCTIONS ================================================== /** * @notice Checks whether one to one matches can be executed * @dev This function is called by the main exchange to check whether one to one matches can be executed. It checks whether orders have the right constraints - i.e they have one specific NFT only, whether time is still valid, prices are valid and whether the nfts intersect. * @param makerOrder1 first makerOrder * @param makerOrder2 second makerOrder * @return returns whether the order can be executed, orderHashes and the execution price */ function canExecMatchOneToOne(OrderTypes.MakerOrder calldata makerOrder1, OrderTypes.MakerOrder calldata makerOrder2) external view override returns ( bool, bytes32, bytes32, uint256 ) { // check if the orders are valid bytes32 sellOrderHash = _hash(makerOrder1); bytes32 buyOrderHash = _hash(makerOrder2); require(verifyMatchOneToOneOrders(sellOrderHash, buyOrderHash, makerOrder1, makerOrder2), 'order not verified'); // check constraints bool numItemsValid = makerOrder2.constraints[0] == makerOrder1.constraints[0] && makerOrder2.constraints[0] == 1 && makerOrder2.nfts.length == 1 && makerOrder2.nfts[0].tokens.length == 1 && makerOrder1.nfts.length == 1 && makerOrder1.nfts[0].tokens.length == 1; bool _isTimeValid = makerOrder2.constraints[3] <= block.timestamp && makerOrder2.constraints[4] >= block.timestamp && makerOrder1.constraints[3] <= block.timestamp && makerOrder1.constraints[4] >= block.timestamp; bool _isPriceValid; uint256 makerOrder1Price = _getCurrentPrice(makerOrder1); uint256 makerOrder2Price = _getCurrentPrice(makerOrder2); uint256 execPrice; if (makerOrder1.isSellOrder) { _isPriceValid = makerOrder2Price >= makerOrder1Price; execPrice = makerOrder1Price; } else { _isPriceValid = makerOrder1Price >= makerOrder2Price; execPrice = makerOrder2Price; } return ( numItemsValid && _isTimeValid && doItemsIntersect(makerOrder1.nfts, makerOrder2.nfts) && _isPriceValid, sellOrderHash, buyOrderHash, execPrice ); } /** * @notice Checks whether one to many matches can be executed * @dev This function is called by the main exchange to check whether one to many matches can be executed. It checks whether orders have the right constraints - i.e they have the right number of items, whether time is still valid, prices are valid and whether the nfts intersect. All orders are expected to contain specific items. * @param makerOrder the one makerOrder * @param manyMakerOrders many maker orders * @return returns whether the order can be executed and orderHash of the one side order */ function canExecMatchOneToMany( OrderTypes.MakerOrder calldata makerOrder, OrderTypes.MakerOrder[] calldata manyMakerOrders ) external view override returns (bool, bytes32) { // check if makerOrder is valid bytes32 makerOrderHash = _hash(makerOrder); require(isOrderValid(makerOrder, makerOrderHash), 'invalid maker order'); // check the constraints of the 'one' maker order uint256 numNftsInOneOrder; for (uint256 i; i < makerOrder.nfts.length; ) { numNftsInOneOrder = numNftsInOneOrder + makerOrder.nfts[i].tokens.length; unchecked { ++i; } } // check the constraints of many maker orders uint256 totalNftsInManyOrders; bool numNftsPerManyOrderValid = true; bool isOrdersTimeValid = true; bool itemsIntersect = true; for (uint256 i; i < manyMakerOrders.length; ) { uint256 nftsLength = manyMakerOrders[i].nfts.length; uint256 numNftsPerOrder; for (uint256 j; j < nftsLength; ) { numNftsPerOrder = numNftsPerOrder + manyMakerOrders[i].nfts[j].tokens.length; unchecked { ++j; } } numNftsPerManyOrderValid = numNftsPerManyOrderValid && manyMakerOrders[i].constraints[0] == numNftsPerOrder; totalNftsInManyOrders = totalNftsInManyOrders + numNftsPerOrder; isOrdersTimeValid = isOrdersTimeValid && manyMakerOrders[i].constraints[3] <= block.timestamp && manyMakerOrders[i].constraints[4] >= block.timestamp; itemsIntersect = itemsIntersect && doItemsIntersect(makerOrder.nfts, manyMakerOrders[i].nfts); if (!numNftsPerManyOrderValid) { return (false, makerOrderHash); // short circuit } unchecked { ++i; } } bool _isTimeValid = isOrdersTimeValid && makerOrder.constraints[3] <= block.timestamp && makerOrder.constraints[4] >= block.timestamp; uint256 currentMakerOrderPrice = _getCurrentPrice(makerOrder); uint256 sumCurrentOrderPrices = _sumCurrentPrices(manyMakerOrders); bool _isPriceValid; if (makerOrder.isSellOrder) { _isPriceValid = sumCurrentOrderPrices >= currentMakerOrderPrice; } else { _isPriceValid = sumCurrentOrderPrices <= currentMakerOrderPrice; } return ( numNftsInOneOrder == makerOrder.constraints[0] && numNftsInOneOrder == totalNftsInManyOrders && _isTimeValid && itemsIntersect && _isPriceValid, makerOrderHash ); } /** * @notice Checks whether match orders with a higher level intent can be executed * @dev This function is called by the main exchange to check whether one to one matches can be executed. It checks whether orders have the right constraints - i.e they have the right number of items, whether time is still valid, prices are valid and whether the nfts intersect * @param sell sell order * @param buy buy order * @param constructedNfts - nfts constructed by the off chain matching engine * @return returns whether the order can be execute, orderHashes and the execution price */ function canExecMatchOrder( OrderTypes.MakerOrder calldata sell, OrderTypes.MakerOrder calldata buy, OrderTypes.OrderItem[] calldata constructedNfts ) external view override returns ( bool, bytes32, bytes32, uint256 ) { // check if orders are valid bytes32 sellOrderHash = _hash(sell); bytes32 buyOrderHash = _hash(buy); require(verifyMatchOrders(sellOrderHash, buyOrderHash, sell, buy), 'order not verified'); (bool _isPriceValid, uint256 execPrice) = isPriceValid(sell, buy); return ( isTimeValid(sell, buy) && _isPriceValid && areNumMatchItemsValid(sell, buy, constructedNfts) && doItemsIntersect(sell.nfts, constructedNfts) && doItemsIntersect(buy.nfts, constructedNfts), sellOrderHash, buyOrderHash, execPrice ); } /** * @notice Checks whether one to one taker orders can be executed * @dev This function is called by the main exchange to check whether one to one taker orders can be executed. It checks whether orders have the right constraints - i.e they have one NFT only and whether time is still valid * @param makerOrder the makerOrder * @return returns whether the order can be executed and makerOrderHash */ function canExecTakeOneOrder(OrderTypes.MakerOrder calldata makerOrder) external view override returns (bool, bytes32) { // check if makerOrder is valid bytes32 makerOrderHash = _hash(makerOrder); require(isOrderValid(makerOrder, makerOrderHash), 'invalid maker order'); bool numItemsValid = makerOrder.constraints[0] == 1 && makerOrder.nfts.length == 1 && makerOrder.nfts[0].tokens.length == 1; bool _isTimeValid = makerOrder.constraints[3] <= block.timestamp && makerOrder.constraints[4] >= block.timestamp; return (numItemsValid && _isTimeValid, makerOrderHash); } /** * @notice Checks whether take orders with a higher level intent can be executed * @dev This function is called by the main exchange to check whether take orders with a higher level intent can be executed. It checks whether orders have the right constraints - i.e they have the right number of items, whether time is still valid and whether the nfts intersect * @param makerOrder the maker order * @param takerItems the taker items specified by the taker * @return returns whether order can be executed and the makerOrderHash */ function canExecTakeOrder(OrderTypes.MakerOrder calldata makerOrder, OrderTypes.OrderItem[] calldata takerItems) external view override returns (bool, bytes32) { // check if makerOrder is valid bytes32 makerOrderHash = _hash(makerOrder); require(isOrderValid(makerOrder, makerOrderHash), 'invalid maker order'); return ( makerOrder.constraints[3] <= block.timestamp && makerOrder.constraints[4] >= block.timestamp && areNumTakerItemsValid(makerOrder, takerItems) && doItemsIntersect(makerOrder.nfts, takerItems), makerOrderHash ); } // ======================================================= PUBLIC FUNCTIONS ================================================== /** * @notice Checks whether orders are valid * @dev Checks whether currencies match, sides match, complications match and if each order is valid (see isOrderValid) * @param sellOrderHash hash of the sell order * @param buyOrderHash hash of the buy order * @param sell the sell order * @param buy the buy order * @return whether orders are valid */ function verifyMatchOneToOneOrders( bytes32 sellOrderHash, bytes32 buyOrderHash, OrderTypes.MakerOrder calldata sell, OrderTypes.MakerOrder calldata buy ) public view returns (bool) { bool currenciesMatch = sell.execParams[1] == buy.execParams[1] || (sell.execParams[1] == address(0) && buy.execParams[1] == WETH); return (sell.isSellOrder && !buy.isSellOrder && sell.execParams[0] == buy.execParams[0] && sell.signer != buy.signer && currenciesMatch && isOrderValid(sell, sellOrderHash) && isOrderValid(buy, buyOrderHash)); } /** * @notice Checks whether orders are valid * @dev Checks whether currencies match, sides match, complications match and if each order is valid (see isOrderValid) * @param sell the sell order * @param buy the buy order * @return whether orders are valid and orderHash */ function verifyMatchOneToManyOrders( bool verifySellOrder, OrderTypes.MakerOrder calldata sell, OrderTypes.MakerOrder calldata buy ) public view override returns (bool, bytes32) { bool currenciesMatch = sell.execParams[1] == buy.execParams[1] || (sell.execParams[1] == address(0) && buy.execParams[1] == WETH); bool _orderValid; bytes32 orderHash; if (verifySellOrder) { orderHash = _hash(sell); _orderValid = isOrderValid(sell, orderHash); } else { orderHash = _hash(buy); _orderValid = isOrderValid(buy, orderHash); } return ( sell.isSellOrder && !buy.isSellOrder && sell.execParams[0] == buy.execParams[0] && sell.signer != buy.signer && currenciesMatch && _orderValid, orderHash ); } /** * @notice Checks whether orders are valid * @dev Checks whether currencies match, sides match, complications match and if each order is valid (see isOrderValid) Also checks if the given complication can execute this order * @param sellOrderHash hash of the sell order * @param buyOrderHash hash of the buy order * @param sell the sell order * @param buy the buy order * @return whether orders are valid */ function verifyMatchOrders( bytes32 sellOrderHash, bytes32 buyOrderHash, OrderTypes.MakerOrder calldata sell, OrderTypes.MakerOrder calldata buy ) public view returns (bool) { bool currenciesMatch = sell.execParams[1] == buy.execParams[1] || (sell.execParams[1] == address(0) && buy.execParams[1] == WETH); return (sell.isSellOrder && !buy.isSellOrder && sell.execParams[0] == buy.execParams[0] && sell.signer != buy.signer && currenciesMatch && isOrderValid(sell, sellOrderHash) && isOrderValid(buy, buyOrderHash)); } /** * @notice Verifies the validity of the order * @dev checks if signature is valid and if the complication and currency are valid * @param order the order * @param orderHash computed hash of the order * @return whether the order is valid */ function isOrderValid(OrderTypes.MakerOrder calldata order, bytes32 orderHash) public view returns (bool) { // Verify the validity of the signature (bytes32 r, bytes32 s, uint8 v) = abi.decode(order.sig, (bytes32, bytes32, uint8)); bool sigValid = SignatureChecker.verify(orderHash, order.signer, r, s, v, DOMAIN_SEPARATOR); return (sigValid && order.execParams[0] == address(this) && _currencies.contains(order.execParams[1])); } /// @dev checks whether the orders are expired function isTimeValid(OrderTypes.MakerOrder calldata sell, OrderTypes.MakerOrder calldata buy) public view returns (bool) { return sell.constraints[3] <= block.timestamp && sell.constraints[4] >= block.timestamp && buy.constraints[3] <= block.timestamp && buy.constraints[4] >= block.timestamp; } /// @dev checks whether the price is valid; a buy order should always have a higher price than a sell order function isPriceValid(OrderTypes.MakerOrder calldata sell, OrderTypes.MakerOrder calldata buy) public view returns (bool, uint256) { (uint256 currentSellPrice, uint256 currentBuyPrice) = (_getCurrentPrice(sell), _getCurrentPrice(buy)); return (currentBuyPrice >= currentSellPrice, currentSellPrice); } /// @dev sanity check to make sure the constructed nfts conform to the user signed constraints function areNumMatchItemsValid( OrderTypes.MakerOrder calldata sell, OrderTypes.MakerOrder calldata buy, OrderTypes.OrderItem[] calldata constructedNfts ) public pure returns (bool) { uint256 numConstructedItems; for (uint256 i; i < constructedNfts.length; ) { unchecked { numConstructedItems = numConstructedItems + constructedNfts[i].tokens.length; ++i; } } return numConstructedItems >= buy.constraints[0] && numConstructedItems <= sell.constraints[0]; } /// @dev sanity check to make sure that a taker is specifying the right number of items function areNumTakerItemsValid(OrderTypes.MakerOrder calldata makerOrder, OrderTypes.OrderItem[] calldata takerItems) public pure returns (bool) { uint256 numTakerItems; for (uint256 i; i < takerItems.length; ) { unchecked { numTakerItems = numTakerItems + takerItems[i].tokens.length; ++i; } } return makerOrder.constraints[0] == numTakerItems; } /** * @notice Checks whether nfts intersect * @dev This function checks whether there are intersecting nfts between two orders * @param order1Nfts nfts in the first order * @param order2Nfts nfts in the second order * @return returns whether items intersect */ function doItemsIntersect(OrderTypes.OrderItem[] calldata order1Nfts, OrderTypes.OrderItem[] calldata order2Nfts) public pure returns (bool) { uint256 order1NftsLength = order1Nfts.length; uint256 order2NftsLength = order2Nfts.length; // case where maker/taker didn't specify any items if (order1NftsLength == 0 || order2NftsLength == 0) { return true; } uint256 numCollsMatched; unchecked { for (uint256 i; i < order2NftsLength; ) { for (uint256 j; j < order1NftsLength; ) { if (order1Nfts[j].collection == order2Nfts[i].collection) { // increment numCollsMatched ++numCollsMatched; // check if tokenIds intersect bool tokenIdsIntersect = doTokenIdsIntersect(order1Nfts[j], order2Nfts[i]); require(tokenIdsIntersect, 'tokenIds dont intersect'); // short circuit break; } ++j; } ++i; } } return numCollsMatched == order2NftsLength; } /** * @notice Checks whether tokenIds intersect * @dev This function checks whether there are intersecting tokenIds between two order items * @param item1 first item * @param item2 second item * @return returns whether tokenIds intersect */ function doTokenIdsIntersect(OrderTypes.OrderItem calldata item1, OrderTypes.OrderItem calldata item2) public pure returns (bool) { uint256 item1TokensLength = item1.tokens.length; uint256 item2TokensLength = item2.tokens.length; // case where maker/taker didn't specify any tokenIds for this collection if (item1TokensLength == 0 || item2TokensLength == 0) { return true; } uint256 numTokenIdsPerCollMatched; unchecked { for (uint256 k; k < item2TokensLength; ) { for (uint256 l; l < item1TokensLength; ) { if (item1.tokens[l].tokenId == item2.tokens[k].tokenId) { // increment numTokenIdsPerCollMatched ++numTokenIdsPerCollMatched; // short circuit break; } ++l; } ++k; } } return numTokenIdsPerCollMatched == item2TokensLength; } // ======================================================= UTILS ============================================================ /// @dev hashes the given order with the help of _nftsHash and _tokensHash function _hash(OrderTypes.MakerOrder calldata order) internal pure returns (bytes32) { return keccak256( abi.encode( ORDER_HASH, order.isSellOrder, order.signer, keccak256(abi.encodePacked(order.constraints)), _nftsHash(order.nfts), keccak256(abi.encodePacked(order.execParams)), keccak256(order.extraParams) ) ); } function _nftsHash(OrderTypes.OrderItem[] calldata nfts) internal pure returns (bytes32) { bytes32[] memory hashes = new bytes32[](nfts.length); for (uint256 i; i < nfts.length; ) { bytes32 hash = keccak256(abi.encode(ORDER_ITEM_HASH, nfts[i].collection, _tokensHash(nfts[i].tokens))); hashes[i] = hash; unchecked { ++i; } } bytes32 nftsHash = keccak256(abi.encodePacked(hashes)); return nftsHash; } function _tokensHash(OrderTypes.TokenInfo[] calldata tokens) internal pure returns (bytes32) { bytes32[] memory hashes = new bytes32[](tokens.length); for (uint256 i; i < tokens.length; ) { bytes32 hash = keccak256(abi.encode(TOKEN_INFO_HASH, tokens[i].tokenId, tokens[i].numTokens)); hashes[i] = hash; unchecked { ++i; } } bytes32 tokensHash = keccak256(abi.encodePacked(hashes)); return tokensHash; } /// @dev returns the sum of current order prices; used in match one to many orders function _sumCurrentPrices(OrderTypes.MakerOrder[] calldata orders) internal view returns (uint256) { uint256 sum; uint256 ordersLength = orders.length; for (uint256 i; i < ordersLength; ) { sum = sum + _getCurrentPrice(orders[i]); unchecked { ++i; } } return sum; } /// @dev Gets current order price for orders that vary in price over time (dutch and reverse dutch auctions) function _getCurrentPrice(OrderTypes.MakerOrder calldata order) internal view returns (uint256) { (uint256 startPrice, uint256 endPrice) = (order.constraints[1], order.constraints[2]); if (startPrice == endPrice) { return startPrice; } uint256 duration = order.constraints[4] - order.constraints[3]; if (duration == 0) { return startPrice; } uint256 elapsedTime = block.timestamp - order.constraints[3]; unchecked { uint256 portionBps = elapsedTime > duration ? PRECISION : ((elapsedTime * PRECISION) / duration); if (startPrice > endPrice) { uint256 priceDiff = ((startPrice - endPrice) * portionBps) / PRECISION; return startPrice - priceDiff; } else { uint256 priceDiff = ((endPrice - startPrice) * portionBps) / PRECISION; return startPrice + priceDiff; } } } // ======================================================= OWNER FUNCTIONS ============================================================ /// @dev adds a new transaction currency to the exchange function addCurrency(address _currency) external onlyOwner { _currencies.add(_currency); emit CurrencyAdded(_currency); } /// @dev removes a transaction currency from the exchange function removeCurrency(address _currency) external onlyOwner { _currencies.remove(_currency); emit CurrencyRemoved(_currency); } // ======================================================= VIEW FUNCTIONS ============================================================ /// @notice returns the number of currencies supported by the exchange function numCurrencies() external view returns (uint256) { return _currencies.length(); } /// @notice returns the currency at the given index function getCurrencyAt(uint256 index) external view returns (address) { return _currencies.at(index); } /// @notice returns whether a given currency is valid function isValidCurrency(address currency) external view returns (bool) { return _currencies.contains(currency); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @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 is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @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() public virtual 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) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.14; import {Address} from '@openzeppelin/contracts/utils/Address.sol'; import {IERC1271} from '@openzeppelin/contracts/interfaces/IERC1271.sol'; /** * @title SignatureChecker * @notice This library allows verification of signatures for both EOAs and contracts */ library SignatureChecker { /** * @notice Recovers the signer of a signature (for EOA) * @param hashed hash containing the signed message * @param r parameter * @param s parameter * @param v parameter (27 or 28). This prevents malleability since the public key recovery equation has two possible solutions. */ function recover( bytes32 hashed, bytes32 r, bytes32 s, uint8 v ) internal pure returns (address) { // https://ethereum.stackexchange.com/questions/83174/is-it-best-practice-to-check-signature-malleability-in-ecrecover // https://crypto.iacr.org/2019/affevents/wac/medias/Heninger-BiasedNonceSense.pdf require( uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, 'Signature: Invalid s parameter' ); require(v == 27 || v == 28, 'Signature: Invalid v parameter'); // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hashed, v, r, s); require(signer != address(0), 'Signature: Invalid signer'); return signer; } /** * @notice Returns whether the signer matches the signed message * @param orderHash the hash containing the signed message * @param signer the signer address to confirm message validity * @param r parameter * @param s parameter * @param v parameter (27 or 28) this prevents malleability since the public key recovery equation has two possible solutions * @param domainSeparator parameter to prevent signature being executed in other chains and environments * @return true --> if valid // false --> if invalid */ function verify( bytes32 orderHash, address signer, bytes32 r, bytes32 s, uint8 v, bytes32 domainSeparator ) internal view returns (bool) { // \x19\x01 is the standardized encoding prefix // https://eips.ethereum.org/EIPS/eip-712#specification bytes32 digest = keccak256(abi.encodePacked('\x19\x01', domainSeparator, orderHash)); if (Address.isContract(signer)) { // 0x1626ba7e is the interfaceId for signature contracts (see IERC1271) return IERC1271(signer).isValidSignature(digest, abi.encodePacked(r, s, v)) == 0x1626ba7e; } else { return recover(digest, r, s, v) == signer; } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.14; /** * @title OrderTypes * @author nneverlander. Twitter @nneverlander * @notice This library contains the order types used by the main exchange and complications */ library OrderTypes { /// @dev the tokenId and numTokens (==1 for ERC721) struct TokenInfo { uint256 tokenId; uint256 numTokens; } /// @dev an order item is a collection address and tokens from that collection struct OrderItem { address collection; TokenInfo[] tokens; } struct MakerOrder { ///@dev is order sell or buy bool isSellOrder; ///@dev signer of the order (maker address) address signer; ///@dev Constraints array contains the order constraints. Total constraints: 7. In order: // numItems - min (for buy orders) / max (for sell orders) number of items in the order // start price in wei // end price in wei // start time in block.timestamp // end time in block.timestamp // nonce of the order // max tx.gasprice in wei that a user is willing to pay for gas uint256[] constraints; ///@dev nfts array contains order items where each item is a collection and its tokenIds OrderItem[] nfts; ///@dev address of complication for trade execution (e.g. InfinityOrderBookComplication), address of the currency (e.g., WETH) address[] execParams; ///@dev additional parameters like traits for trait orders, private sale buyer for OTC orders etc bytes extraParams; ///@dev the order signature uint8 v: parameter (27 or 28), bytes32 r, bytes32 s bytes sig; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.14; import {OrderTypes} from '../libs/OrderTypes.sol'; /** * @title IComplication * @author nneverlander. Twitter @nneverlander * @notice Complication interface that must be implemented by all complications (execution strategies) */ interface IComplication { function canExecMatchOneToOne(OrderTypes.MakerOrder calldata makerOrder1, OrderTypes.MakerOrder calldata makerOrder2) external view returns ( bool, bytes32, bytes32, uint256 ); function canExecMatchOneToMany( OrderTypes.MakerOrder calldata makerOrder, OrderTypes.MakerOrder[] calldata manyMakerOrders ) external view returns (bool, bytes32); function canExecMatchOrder( OrderTypes.MakerOrder calldata sell, OrderTypes.MakerOrder calldata buy, OrderTypes.OrderItem[] calldata constructedNfts ) external view returns ( bool, bytes32, bytes32, uint256 ); function canExecTakeOneOrder(OrderTypes.MakerOrder calldata makerOrder) external view returns (bool, bytes32); function canExecTakeOrder(OrderTypes.MakerOrder calldata makerOrder, OrderTypes.OrderItem[] calldata takerItems) external view returns (bool, bytes32); function verifyMatchOneToManyOrders( bool verifySellOrder, OrderTypes.MakerOrder calldata sell, OrderTypes.MakerOrder calldata buy ) external view returns (bool, bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * _Available since v4.1._ */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
{ "viaIR": true, "optimizer": { "enabled": true, "runs": 99999999 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"currency","type":"address"}],"name":"CurrencyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"currency","type":"address"}],"name":"CurrencyRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORDER_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORDER_ITEM_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN_INFO_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_currency","type":"address"}],"name":"addCurrency","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"sell","type":"tuple"},{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"buy","type":"tuple"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"constructedNfts","type":"tuple[]"}],"name":"areNumMatchItemsValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"makerOrder","type":"tuple"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"takerItems","type":"tuple[]"}],"name":"areNumTakerItemsValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"makerOrder","type":"tuple"},{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder[]","name":"manyMakerOrders","type":"tuple[]"}],"name":"canExecMatchOneToMany","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"makerOrder1","type":"tuple"},{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"makerOrder2","type":"tuple"}],"name":"canExecMatchOneToOne","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"sell","type":"tuple"},{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"buy","type":"tuple"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"constructedNfts","type":"tuple[]"}],"name":"canExecMatchOrder","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"makerOrder","type":"tuple"}],"name":"canExecTakeOneOrder","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"makerOrder","type":"tuple"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"takerItems","type":"tuple[]"}],"name":"canExecTakeOrder","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"order1Nfts","type":"tuple[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"order2Nfts","type":"tuple[]"}],"name":"doItemsIntersect","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem","name":"item1","type":"tuple"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem","name":"item2","type":"tuple"}],"name":"doTokenIdsIntersect","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getCurrencyAt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"order","type":"tuple"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"isOrderValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"sell","type":"tuple"},{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"buy","type":"tuple"}],"name":"isPriceValid","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"sell","type":"tuple"},{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"buy","type":"tuple"}],"name":"isTimeValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"currency","type":"address"}],"name":"isValidCurrency","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numCurrencies","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_currency","type":"address"}],"name":"removeCurrency","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"verifySellOrder","type":"bool"},{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"sell","type":"tuple"},{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"buy","type":"tuple"}],"name":"verifyMatchOneToManyOrders","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"sellOrderHash","type":"bytes32"},{"internalType":"bytes32","name":"buyOrderHash","type":"bytes32"},{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"sell","type":"tuple"},{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"buy","type":"tuple"}],"name":"verifyMatchOneToOneOrders","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"sellOrderHash","type":"bytes32"},{"internalType":"bytes32","name":"buyOrderHash","type":"bytes32"},{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"sell","type":"tuple"},{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder","name":"buy","type":"tuple"}],"name":"verifyMatchOrders","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a08060405234620001175760008054336001600160a01b0319821681178355926001600160a01b03909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36200005962000166565b8051602091820120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f9381019384527fd00f7e0da676e82502766333453d9e2dd0b5eb5246543a7459a7ba2fed40df8f9181019190915260608101919091524660808201523060a0808301919091528152620000db60c08262000133565b519020608052620000eb620001a5565b50620000f662000259565b50604051612f199081620002e182396080518181816103730152611cf70152f35b600080fd5b50634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b038211908210176200015757604052565b620001616200011c565b604052565b60408051919082016001600160401b0381118382101762000195575b60405260018252603160f81b6020830152565b6200019f6200011c565b62000182565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2600081815260026020527fde032e96a833a2191f55c5766e34554d9b07734477ea9cb69c40158c1078e79354909190620002555760019182546801000000000000000081101562000245575b8381018085558110156200023157908260409285835260208320015583549281526002602052205590565b634e487b7160e01b82526032600452602482fd5b6200024f6200011c565b62000206565b5090565b600080805260026020527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b54620002dd57600190815468010000000000000000811015620002cd575b8281018084558110156200023157819083825260208220015560408254918080526002602052205590565b620002d76200011c565b620002a2565b9056fe60806040526004361015610013575b600080fd5b60003560e01c80631d49c1ef1461024e5780633051b935146101f45780633644e5151461024557806336ce5c7a1461023c5780633e4e4f8b146102335780634fb925581461022a57806355de2746146102215780635ce3907314610218578063715018a61461020f5780637720595d146102065780637b866a1d146101fd578063829a2307146101f457806383d12146146101eb5780638ab234b6146101e25780638da5cb5b146101d95780638e2c7d85146101d0578063950c52bb146101c75780639e0daf5e146101be578063aaf5eb68146101b5578063ad5c4648146101ac578063b66948cf146101a3578063b79707411461019a578063c291c1d514610191578063c5d3a10714610188578063d9814ac51461017f578063f1332a9114610176578063f2fde38b1461016d578063f7a0e3f4146101645763fd2596281461015c57600080fd5b61000e611390565b5061000e611376565b5061000e611280565b5061000e611254565b5061000e61101d565b5061000e610f8f565b5061000e610f72565b5061000e610f18565b5061000e610ea2565b5061000e610e46565b5061000e610e0a565b5061000e610cc7565b5061000e610bc5565b5061000e610ad1565b5061000e610a7e565b5061000e6109e6565b5061000e6107a5565b5061000e6102b6565b5061000e610741565b5061000e6106ae565b5061000e610606565b5061000e6105c9565b5061000e6105af565b5061000e6104ac565b5061000e610459565b5061000e610396565b5061000e61033c565b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760206040517f7bcfb5a29031e6b8d34ca1a14dd0a1f5cb11b20f755bb2a31ee3c4b143477e4a8152f35b908160e091031261000e5790565b503461000e5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5767ffffffffffffffff60443581811161000e576103079036906004016102a8565b9060643590811161000e576020916103266103329236906004016102a8565b90602435600435611af9565b6040519015158152f35b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b503461000e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760043567ffffffffffffffff811161000e576103326103eb60209236906004016102a8565b60243590611cb8565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261000e5767ffffffffffffffff60043581811161000e578361043f916004016102a8565b9260243591821161000e57610456916004016102a8565b90565b503461000e57604061047f610477610470366103f4565b9190612707565b918291612707565b10159082519182526020820152f35b73ffffffffffffffffffffffffffffffffffffffff81160361000e57565b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5773ffffffffffffffffffffffffffffffffffffffff6004356104fd8161048e565b16600052600260205260206040600020541515604051908152f35b9181601f8401121561000e5782359167ffffffffffffffff831161000e576020808501948460051b01011161000e57565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261000e5767ffffffffffffffff60043581811161000e5783610594916004016102a8565b9260243591821161000e576105ab91600401610518565b9091565b503461000e5760206103326105c336610549565b91611edd565b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576020600154604051908152f35b503461000e576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106ab5780547fffffffffffffffffffffffff000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff82169161067d33841461146e565b16825581604051917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08284a3f35b80fd5b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57602073ffffffffffffffffffffffffffffffffffffffff600435600154811015610734575b60016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6015416604051908152f35b61073c6115fb565b610703565b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760206040517f88f0bd19d14f8b5d22c0605a15d9fffc285ebc8c86fb21139456d305982906f18152f35b8015150361000e57565b503461000e5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576004356107e18161079b565b67ffffffffffffffff9060243582811161000e576108039036906004016102a8565b9160443590811161000e5761081c9036906004016102a8565b608083019161083c61083761083185876115a7565b9061162b565b611aef565b91608081019261086e61085561083761083187866115a7565b73ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff80921614928315610997575b1561097d5761089d866122aa565b956108a88782611cb8565b945b6108b38261176d565b9687610965575b8761092c575b505085610900575b505050826108f8575b50816108f0575b506040805191151582526020820192909252f35b0390f35b9050386108d8565b9150386108d1565b61091f91929395506020610918816108559301611aef565b9401611aef565b91161415913880806108c8565b82975061085561083761094d61095361083761094d61095a968a98996115a7565b90611646565b95886115a7565b9116149438806108c0565b96506109776109738561176d565b1590565b966108ba565b610986826122aa565b956109918784611cb8565b946108aa565b9250806109aa610837610831888a6115a7565b1615806109b8575b9261088f565b5073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2816109df61083761083188876115a7565b16146109b2565b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e577fe0390a89516146ccfb796a9fbfc3f7646282194c554d05020484599ee992dd5a6020600435610a458161048e565b73ffffffffffffffffffffffffffffffffffffffff90610a6a8260005416331461146e565b16610a7481612806565b50604051908152a1005b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b503461000e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5767ffffffffffffffff60043581811161000e57610b22903690600401610518565b60249291923591821161000e57602092610b43610332933690600401610518565b929091611f9a565b60607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261000e5767ffffffffffffffff9160043583811161000e5782610b96916004016102a8565b9260243581811161000e5783610bae916004016102a8565b9260443591821161000e576105ab91600401610518565b503461000e57610bd436610b4b565b9290610bdf826122aa565b93610be9846122aa565b90610bfe610bf98686858a611af9565b611542565b610c0784612707565b9283610c1287612707565b101594610c1f8782611da9565b9586610cbf575b5085610cab575b85610c8e575b5084610c67575b50506108ec9293506040519485948590949392606092608083019615158352602083015260408201520152565b6108ec9450610c7e866060610c84959801906115a7565b90611f9a565b9150823880610c3a565b81610ca4929650610c7e826060869401906115a7565b9338610c33565b9450610cb982828888611e53565b94610c2d565b955038610c26565b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760043567ffffffffffffffff811161000e57610d179036906004016102a8565b610d20816122aa565b90610d33610d2e8383611cb8565b611777565b60408101906001610d4483836115a7565b15610dfd575b35149182610de3575b82610db3575b610d6c610d6682846115a7565b90611657565b354210159182610d92575b5050816108f057506040805191151582526020820192909252f35b610da9925090610da1916115a7565b429291611666565b3510153880610d77565b91506001610dda610dd0610dca60608501856115a7565b90611684565b6020810190611719565b90501491610d59565b91506001610df460608301836115a7565b90501491610d53565b610e056115fb565b610d4a565b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760206040516127108152f35b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57602060405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28152f35b9081604091031261000e5790565b503461000e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5767ffffffffffffffff60043581811161000e57610ef3903690600401610e94565b9060243590811161000e57602091610f12610332923690600401610e94565b90612071565b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760206040517ff73f37e9f570369ceaab59cef16249ae1c0ad1afd592d656afac0be6f63b87e08152f35b503461000e576020610332610f8636610b4b565b92919091611e53565b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e577fa40d69111be14f29022626d38310e47cc2d7f4cb728961509c2f65a4bee08c5b6020600435610fee8161048e565b73ffffffffffffffffffffffffffffffffffffffff906110138260005416331461146e565b16610a748161293d565b503461000e5761102c366103f4565b90611036816122aa565b91611040816122aa565b91611050610bf983838688611af9565b604082019061106261094d83856115a7565b3592604082019361107661094d86856115a7565b3514938461123b575b84611221575b84611201575b846111e7575b846111c7575b6110a4610d6685846115a7565b3542101593846111ad575b508361118d575b83611173575b506000916110c981612707565b926110d383612707565b90506110de8261176d565b156111685783111592935b85611160575b5084611133575b505082611129575b506108ec91926040519485948590949392606092608083019615158352602083015260408201520152565b91506108ec6110fe565b6111589294509061114b826060610b439401906115a7565b92909160608101906115a7565b9138806110f6565b9450386110ef565b8093101592936110e9565b611183919350610da190836115a7565b35101591386110bc565b92506111a461119c84846115a7565b429291611657565b351115926110b6565b6111bd919450610da190836115a7565b35101592386110af565b935060016111de610dd0610dca60608601866115a7565b90501493611097565b935060016111f860608401846115a7565b90501493611091565b93506001611218610dd0610dca60608501856115a7565b9050149361108b565b9350600161123260608301836115a7565b90501493611085565b9350600161124c61094d85846115a7565b35149361107f565b503461000e5761126c61126636610549565b9161186e565b604080519215158352602083019190915290f35b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576004356112bc8161048e565b73ffffffffffffffffffffffffffffffffffffffff6112e08160005416331461146e565b8116156112f2576112f0906114d3565b005b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b503461000e57602061033261138a366103f4565b90611da9565b503461000e5761139f36610549565b6113aa8392936122aa565b926113b8610d2e8585611cb8565b60408301926113c784826115a7565b60031015611461575b60604291013511159384611430575b508361141d575b83611402575b5050604080519215158352602083019390935250f35b6114159350806060610c7e9201906115a7565b3880806113ec565b925061142a828285611edd565b926113e6565b8161143c9295506115a7565b60041015611454575b608042910135101592386113df565b61145c6115fb565b611445565b6114696115fb565b6113d0565b1561147557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b6000549073ffffffffffffffffffffffffffffffffffffffff80911691827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e06000604051a3565b1561154957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6f72646572206e6f7420766572696669656400000000000000000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561000e570180359067ffffffffffffffff821161000e57602001918160051b3603831361000e57565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020916001101561163a570190565b6116426115fb565b0190565b901561164f5790565b6104566115fb565b6060916003101561163a570190565b6080916004101561163a570190565b6040916002101561163a570190565b90156116be575b8035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18136030182121561000e570190565b6116c66115fb565b61168b565b919081101561170c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18136030182121561000e570190565b6117146115fb565b6116d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561000e570180359067ffffffffffffffff821161000e57602001918160061b3603831361000e57565b356104568161079b565b1561177e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c6964206d616b6572206f72646572000000000000000000000000006044820152fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81198111611818570190565b6116426117dc565b9190811015611861575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218136030182121561000e570190565b6118696115fb565b61182a565b9290919261187b816122aa565b611888610d2e8284611cb8565b600092835b6060840161189b81866115a7565b90508610156118d1576001916118c1610dd0886118bb6118c9958a6115a7565b906116cb565b91905061180c565b94019361188d565b5093509390946000600192839284835b8281106119c5575050836119a9575b83611978575b61192c9161191061094d9261190a89612707565b92612678565b6119198861176d565b15611970571015955b60408101906115a7565b3585149485611966575b50508361195e575b5082611956575b508161195057509190565b90509190565b915038611945565b92503861193e565b1493503880611936565b111595611922565b925061094d61192c9161191061199a61199460408a018a6115a7565b90611666565b354211159592505091506118f6565b92506119bb610d6660408701876115a7565b35421015926118f0565b6119d58184869998979499611820565b956119e5606097888101906115a7565b6000915081905b8985888a848610611ac95750505050505088611aa8575b611a0e90899461180c565b9580611a8d575b80611a72575b9681611a40575b509615611a31576001016118e1565b50505050505050505060009190565b611a6c915080611a55610b43928c018c6115a7565b929091611a6386898b611820565b908101906115a7565b38611a22565b50611a84611994611922848789611820565b35421115611a1b565b50611a9f610d66611922848789611820565b35421015611a15565b9750611a0e88611abf61094d61192286898b611820565b3514989050611a03565b856118bb611ae795611a63600198999a966118c196610dd096611820565b9201906119ec565b356104568161048e565b60808301939192611b1061083761083187846115a7565b6080840190611b2861085561083761083185896115a7565b73ffffffffffffffffffffffffffffffffffffffff80921614918215611c18575b611b528461176d565b9788611c04575b88611bd0575b505086611ba6575b5085611b9e575b5084611b8b575b505082611b8157505090565b6104569250611cb8565b611b96929450611cb8565b913880611b75565b945038611b6e565b909550611bb560208301611aef565b90611bc561085560208701611aef565b911614159438611b67565b82985061085561083761094d611bf261083761094d611bf9968b9998996115a7565b958a6115a7565b911614953880611b5f565b9750611c126109738761176d565b97611b59565b915080611c2b6108376108318a876115a7565b161580611c39575b91611b49565b5073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281611c60610837610831868a6115a7565b1614611c33565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561000e570180359067ffffffffffffffff821161000e5760200191813603831361000e57565b90606090611cc960c0840184611c67565b908093918101031261000e57604082013560ff8116810361000e57611d2492611cf460208601611aef565b927f0000000000000000000000000000000000000000000000000000000000000000936020830135923591612b35565b9081611d76575b81611d34575090565b6104569150610837610831826080611d4d9401906115a7565b73ffffffffffffffffffffffffffffffffffffffff166000526002602052604060002054151590565b9050611d8b61083761094d60808401846115a7565b73ffffffffffffffffffffffffffffffffffffffff16301490611d2b565b9060408201611db881846115a7565b60031015611e46575b60604291013511159283611e15575b505081611dfa575b81611de1575090565b611df49150806040610da19201906115a7565b35101590565b9050611e0c61119c60408301836115a7565b35111590611dd8565b611e209293506115a7565b60041015611e39575b6080429101351015903880611dd0565b611e416115fb565b611e29565b611e4e6115fb565b611dc1565b9260009283915b808310611ebc57505050806040611e729201906115a7565b15611eaf575b358110159182611e8757505090565b611e9791925060408101906115a7565b15611ea25735101590565b611eaa6115fb565b611df4565b611eb76115fb565b611e78565b909193600190611ed0610dd08785876116cb565b9190500194019190611e5a565b909160009283915b808310611f1457505050806040611efd9201906115a7565b15611f0757351490565b611f0f6115fb565b351490565b909193600190611f28610dd08785876116cb565b9190500194019190611ee5565b15611f3c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f746f6b656e49647320646f6e7420696e746572736563740000000000000000006044820152fd5b90918215801561204b575b61204257600092835b858110611fbd57505050501490565b60005b828110611fd1575b50600101611fae565b611fdf6108378285886116cb565b73ffffffffffffffffffffffffffffffffffffffff612005610855610837868c8a6116cb565b91161461201457600101611fc0565b949061203c61203761202c60018095019886896116cb565b610f12848b896116cb565b611f35565b90611fc8565b50505050600190565b508315611fa5565b9190811015612064575b60061b0190565b61206c6115fb565b61205d565b60208101906120808282611719565b91905060208401936120928582611719565b95905083158015612114575b61210957600094855b8781106120b8575050505050501490565b60005b8681106120cc575b506001016120a7565b6120e0816120da8589611719565b90612053565b356120ef836120da8789611719565b35146120fd576001016120bb565b506001968701966120c3565b505050505050600190565b50851561209e565b91907f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811161000e5760051b80928237016000815290565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6080810190811067ffffffffffffffff8211176121a057604052565b6121a8612154565b604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176121a057604052565b9060005b8181106121ff5750505090565b90919260019073ffffffffffffffffffffffffffffffffffffffff85356122258161048e565b168152602090810194019291016121f2565b92919267ffffffffffffffff821161229d575b6040519161228060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601846121ad565b82948184528183011161000e578281602093846000960137010152565b6122a5612154565b61224a565b6122b38161176d565b906124096122e86122c660208401611aef565b6123fd6122d660408601866115a7565b6040519460208601928692849161211c565b039361231a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0958681018352826121ad565b5190209461233461232e60608301836115a7565b906124d4565b9061238361237c61236e61236261234e60808601866115a7565b9290604051928391602083019586916121ee565b038a81018352826121ad565b5190209260a0810190611c67565b3691612237565b6020815191012091604051978895602087019a8b9273ffffffffffffffffffffffffffffffffffffffff60c095929897969360e08601997f7bcfb5a29031e6b8d34ca1a14dd0a1f5cb11b20f755bb2a31ee3c4b143477e4a8752151560208701521660408501526060840152608083015260a08201520152565b039081018352826121ad565b51902090565b60209067ffffffffffffffff8111612429575b60051b0190565b612431612154565b612422565b906124408261240f565b61244d60405191826121ad565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061247b829461240f565b0190602036910137565b602091815181101561249a575b60051b010190565b6124a26115fb565b612492565b805160208092019160005b8281106124c0575050505090565b8351855293810193928101926001016124b2565b906124de81612436565b9160005b82811061252d57505050604051612409816125016020820180956124a7565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018352826121ad565b8061253b60019285856116cb565b356125458161048e565b6125508286866116cb565b6125c361256b61256560209384810190611719565b906125d7565b604080517ff73f37e9f570369ceaab59cef16249ae1c0ad1afd592d656afac0be6f63b87e094810194855273ffffffffffffffffffffffffffffffffffffffff90951660208501528301529091908160608401612501565b5190206125d08287612485565b52016124e2565b906125e181612436565b9160005b82811061260457505050604051612409816125016020820180956124a7565b806126126001928585612053565b35602080612621848888612053565b01356040928351928301937f88f0bd19d14f8b5d22c0605a15d9fffc285ebc8c86fb21139456d305982906f1855283015260609081830152815261266481612184565b5190206126718287612485565b52016125e5565b9060009182915b80831061268c5750505090565b9091926126ae6001916126a86126a3878688611820565b612707565b9061180c565b9301919061267f565b8181106126c2570390565b6126ca6117dc565b0390565b81156126d8570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6040810161271861083182846115a7565b359161272d61272783836115a7565b90611675565b35908184146127bb5761275b61274661199485846115a7565b35612754610d6686856115a7565b35906126b7565b9081156127b457612775610d666127109561277c936115a7565b35426126b7565b90808211156127a357505081905b838181111561279b57030204900390565b900302040190565b836127ae92026126ce565b9061278a565b5050505090565b50505090565b6001548110156127f9575b60016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60190600090565b6128016115fb565b6127cc565b8060005260026020526040600020541560001461289757806001546801000000000000000081101561288a575b600181018060015581101561287d575b7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60155600154906000526002602052604060002055600190565b6128856115fb565b612843565b612892612154565b612833565b50600090565b600154801561290e5760007fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83019280841015612901575b600183520155600155565b6129096115fb565b6128f6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000818152600260205260409020548015612a6c576000918160016129b99310612a5f575b600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff838101928210612a52575b8101908282036129bf575b505050506129a961289d565b6000526002602052604060002090565b55600190565b612a3b927fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf5826129a993612a02951015612a45575b60018a5201549283916127c1565b90919082549060031b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811b9283911b16911916179055565b553880808061299d565b612a4d6115fb565b6129f4565b612a5a6117dc565b612992565b612a676117dc565b612962565b5050600090565b9081602091031261000e57517fffffffff000000000000000000000000000000000000000000000000000000008116810361000e5790565b90929192815260206040818301528351908160408401526000945b828610612b12575050601f817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0926060959611612b05575b0116010190565b6000858286010152612afe565b8581018201518487016060015294810194612ac6565b506040513d6000823e3d90fd5b94612b7f9291949560405193849160208301938490916042927f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201520190565b0392612bb17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0948581018352826121ad565b51902094843b15612cd3579373ffffffffffffffffffffffffffffffffffffffff93612c46602094612c7d946123fd7fffffffff00000000000000000000000000000000000000000000000000000000996040519586938a850191926041937fff00000000000000000000000000000000000000000000000000000000000000928452602084015260f81b1660408201520190565b6040519485809481937f1626ba7e000000000000000000000000000000000000000000000000000000009a8b845260048401612aab565b0392165afa908115612cc6575b600091612c98575b50161490565b612cb9915060203d8111612cbf575b612cb181836121ad565b810190612a73565b38612c92565b503d612ca7565b612cce612b28565b612c8a565b929150612ce09394612dc8565b73ffffffffffffffffffffffffffffffffffffffff90811691161490565b15612d0557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f5369676e61747572653a20496e76616c6964207620706172616d6574657200006044820152fd5b15612d6a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5369676e61747572653a20496e76616c6964207369676e6572000000000000006044820152fd5b9290927f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311612e8557612e3a600093602095612e1460ff8616601b8114908115612e7a575b50612cfe565b604051948594859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa15612e6d575b60005161045673ffffffffffffffffffffffffffffffffffffffff82161515612d63565b612e75612b28565b612e49565b601c91501438612e0e565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f5369676e61747572653a20496e76616c6964207320706172616d6574657200006044820152fdfea2646970667358221220c60af908a2d1daea709ba004d3e35a6a6a02e346b3c411f2fa6b08c2f95450b864736f6c634300080e0033
Deployed Bytecode
0x60806040526004361015610013575b600080fd5b60003560e01c80631d49c1ef1461024e5780633051b935146101f45780633644e5151461024557806336ce5c7a1461023c5780633e4e4f8b146102335780634fb925581461022a57806355de2746146102215780635ce3907314610218578063715018a61461020f5780637720595d146102065780637b866a1d146101fd578063829a2307146101f457806383d12146146101eb5780638ab234b6146101e25780638da5cb5b146101d95780638e2c7d85146101d0578063950c52bb146101c75780639e0daf5e146101be578063aaf5eb68146101b5578063ad5c4648146101ac578063b66948cf146101a3578063b79707411461019a578063c291c1d514610191578063c5d3a10714610188578063d9814ac51461017f578063f1332a9114610176578063f2fde38b1461016d578063f7a0e3f4146101645763fd2596281461015c57600080fd5b61000e611390565b5061000e611376565b5061000e611280565b5061000e611254565b5061000e61101d565b5061000e610f8f565b5061000e610f72565b5061000e610f18565b5061000e610ea2565b5061000e610e46565b5061000e610e0a565b5061000e610cc7565b5061000e610bc5565b5061000e610ad1565b5061000e610a7e565b5061000e6109e6565b5061000e6107a5565b5061000e6102b6565b5061000e610741565b5061000e6106ae565b5061000e610606565b5061000e6105c9565b5061000e6105af565b5061000e6104ac565b5061000e610459565b5061000e610396565b5061000e61033c565b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760206040517f7bcfb5a29031e6b8d34ca1a14dd0a1f5cb11b20f755bb2a31ee3c4b143477e4a8152f35b908160e091031261000e5790565b503461000e5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5767ffffffffffffffff60443581811161000e576103079036906004016102a8565b9060643590811161000e576020916103266103329236906004016102a8565b90602435600435611af9565b6040519015158152f35b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760206040517fdedf095e8071edfabf29861d428463053c7b5a0a215de0d868c31b4cd566b8688152f35b503461000e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760043567ffffffffffffffff811161000e576103326103eb60209236906004016102a8565b60243590611cb8565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261000e5767ffffffffffffffff60043581811161000e578361043f916004016102a8565b9260243591821161000e57610456916004016102a8565b90565b503461000e57604061047f610477610470366103f4565b9190612707565b918291612707565b10159082519182526020820152f35b73ffffffffffffffffffffffffffffffffffffffff81160361000e57565b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5773ffffffffffffffffffffffffffffffffffffffff6004356104fd8161048e565b16600052600260205260206040600020541515604051908152f35b9181601f8401121561000e5782359167ffffffffffffffff831161000e576020808501948460051b01011161000e57565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261000e5767ffffffffffffffff60043581811161000e5783610594916004016102a8565b9260243591821161000e576105ab91600401610518565b9091565b503461000e5760206103326105c336610549565b91611edd565b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576020600154604051908152f35b503461000e576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106ab5780547fffffffffffffffffffffffff000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff82169161067d33841461146e565b16825581604051917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08284a3f35b80fd5b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57602073ffffffffffffffffffffffffffffffffffffffff600435600154811015610734575b60016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6015416604051908152f35b61073c6115fb565b610703565b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760206040517f88f0bd19d14f8b5d22c0605a15d9fffc285ebc8c86fb21139456d305982906f18152f35b8015150361000e57565b503461000e5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576004356107e18161079b565b67ffffffffffffffff9060243582811161000e576108039036906004016102a8565b9160443590811161000e5761081c9036906004016102a8565b608083019161083c61083761083185876115a7565b9061162b565b611aef565b91608081019261086e61085561083761083187866115a7565b73ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff80921614928315610997575b1561097d5761089d866122aa565b956108a88782611cb8565b945b6108b38261176d565b9687610965575b8761092c575b505085610900575b505050826108f8575b50816108f0575b506040805191151582526020820192909252f35b0390f35b9050386108d8565b9150386108d1565b61091f91929395506020610918816108559301611aef565b9401611aef565b91161415913880806108c8565b82975061085561083761094d61095361083761094d61095a968a98996115a7565b90611646565b95886115a7565b9116149438806108c0565b96506109776109738561176d565b1590565b966108ba565b610986826122aa565b956109918784611cb8565b946108aa565b9250806109aa610837610831888a6115a7565b1615806109b8575b9261088f565b5073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2816109df61083761083188876115a7565b16146109b2565b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e577fe0390a89516146ccfb796a9fbfc3f7646282194c554d05020484599ee992dd5a6020600435610a458161048e565b73ffffffffffffffffffffffffffffffffffffffff90610a6a8260005416331461146e565b16610a7481612806565b50604051908152a1005b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b503461000e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5767ffffffffffffffff60043581811161000e57610b22903690600401610518565b60249291923591821161000e57602092610b43610332933690600401610518565b929091611f9a565b60607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261000e5767ffffffffffffffff9160043583811161000e5782610b96916004016102a8565b9260243581811161000e5783610bae916004016102a8565b9260443591821161000e576105ab91600401610518565b503461000e57610bd436610b4b565b9290610bdf826122aa565b93610be9846122aa565b90610bfe610bf98686858a611af9565b611542565b610c0784612707565b9283610c1287612707565b101594610c1f8782611da9565b9586610cbf575b5085610cab575b85610c8e575b5084610c67575b50506108ec9293506040519485948590949392606092608083019615158352602083015260408201520152565b6108ec9450610c7e866060610c84959801906115a7565b90611f9a565b9150823880610c3a565b81610ca4929650610c7e826060869401906115a7565b9338610c33565b9450610cb982828888611e53565b94610c2d565b955038610c26565b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760043567ffffffffffffffff811161000e57610d179036906004016102a8565b610d20816122aa565b90610d33610d2e8383611cb8565b611777565b60408101906001610d4483836115a7565b15610dfd575b35149182610de3575b82610db3575b610d6c610d6682846115a7565b90611657565b354210159182610d92575b5050816108f057506040805191151582526020820192909252f35b610da9925090610da1916115a7565b429291611666565b3510153880610d77565b91506001610dda610dd0610dca60608501856115a7565b90611684565b6020810190611719565b90501491610d59565b91506001610df460608301836115a7565b90501491610d53565b610e056115fb565b610d4a565b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760206040516127108152f35b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57602060405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28152f35b9081604091031261000e5790565b503461000e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5767ffffffffffffffff60043581811161000e57610ef3903690600401610e94565b9060243590811161000e57602091610f12610332923690600401610e94565b90612071565b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760206040517ff73f37e9f570369ceaab59cef16249ae1c0ad1afd592d656afac0be6f63b87e08152f35b503461000e576020610332610f8636610b4b565b92919091611e53565b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e577fa40d69111be14f29022626d38310e47cc2d7f4cb728961509c2f65a4bee08c5b6020600435610fee8161048e565b73ffffffffffffffffffffffffffffffffffffffff906110138260005416331461146e565b16610a748161293d565b503461000e5761102c366103f4565b90611036816122aa565b91611040816122aa565b91611050610bf983838688611af9565b604082019061106261094d83856115a7565b3592604082019361107661094d86856115a7565b3514938461123b575b84611221575b84611201575b846111e7575b846111c7575b6110a4610d6685846115a7565b3542101593846111ad575b508361118d575b83611173575b506000916110c981612707565b926110d383612707565b90506110de8261176d565b156111685783111592935b85611160575b5084611133575b505082611129575b506108ec91926040519485948590949392606092608083019615158352602083015260408201520152565b91506108ec6110fe565b6111589294509061114b826060610b439401906115a7565b92909160608101906115a7565b9138806110f6565b9450386110ef565b8093101592936110e9565b611183919350610da190836115a7565b35101591386110bc565b92506111a461119c84846115a7565b429291611657565b351115926110b6565b6111bd919450610da190836115a7565b35101592386110af565b935060016111de610dd0610dca60608601866115a7565b90501493611097565b935060016111f860608401846115a7565b90501493611091565b93506001611218610dd0610dca60608501856115a7565b9050149361108b565b9350600161123260608301836115a7565b90501493611085565b9350600161124c61094d85846115a7565b35149361107f565b503461000e5761126c61126636610549565b9161186e565b604080519215158352602083019190915290f35b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576004356112bc8161048e565b73ffffffffffffffffffffffffffffffffffffffff6112e08160005416331461146e565b8116156112f2576112f0906114d3565b005b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b503461000e57602061033261138a366103f4565b90611da9565b503461000e5761139f36610549565b6113aa8392936122aa565b926113b8610d2e8585611cb8565b60408301926113c784826115a7565b60031015611461575b60604291013511159384611430575b508361141d575b83611402575b5050604080519215158352602083019390935250f35b6114159350806060610c7e9201906115a7565b3880806113ec565b925061142a828285611edd565b926113e6565b8161143c9295506115a7565b60041015611454575b608042910135101592386113df565b61145c6115fb565b611445565b6114696115fb565b6113d0565b1561147557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b6000549073ffffffffffffffffffffffffffffffffffffffff80911691827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e06000604051a3565b1561154957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6f72646572206e6f7420766572696669656400000000000000000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561000e570180359067ffffffffffffffff821161000e57602001918160051b3603831361000e57565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020916001101561163a570190565b6116426115fb565b0190565b901561164f5790565b6104566115fb565b6060916003101561163a570190565b6080916004101561163a570190565b6040916002101561163a570190565b90156116be575b8035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18136030182121561000e570190565b6116c66115fb565b61168b565b919081101561170c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18136030182121561000e570190565b6117146115fb565b6116d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561000e570180359067ffffffffffffffff821161000e57602001918160061b3603831361000e57565b356104568161079b565b1561177e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c6964206d616b6572206f72646572000000000000000000000000006044820152fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81198111611818570190565b6116426117dc565b9190811015611861575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218136030182121561000e570190565b6118696115fb565b61182a565b9290919261187b816122aa565b611888610d2e8284611cb8565b600092835b6060840161189b81866115a7565b90508610156118d1576001916118c1610dd0886118bb6118c9958a6115a7565b906116cb565b91905061180c565b94019361188d565b5093509390946000600192839284835b8281106119c5575050836119a9575b83611978575b61192c9161191061094d9261190a89612707565b92612678565b6119198861176d565b15611970571015955b60408101906115a7565b3585149485611966575b50508361195e575b5082611956575b508161195057509190565b90509190565b915038611945565b92503861193e565b1493503880611936565b111595611922565b925061094d61192c9161191061199a61199460408a018a6115a7565b90611666565b354211159592505091506118f6565b92506119bb610d6660408701876115a7565b35421015926118f0565b6119d58184869998979499611820565b956119e5606097888101906115a7565b6000915081905b8985888a848610611ac95750505050505088611aa8575b611a0e90899461180c565b9580611a8d575b80611a72575b9681611a40575b509615611a31576001016118e1565b50505050505050505060009190565b611a6c915080611a55610b43928c018c6115a7565b929091611a6386898b611820565b908101906115a7565b38611a22565b50611a84611994611922848789611820565b35421115611a1b565b50611a9f610d66611922848789611820565b35421015611a15565b9750611a0e88611abf61094d61192286898b611820565b3514989050611a03565b856118bb611ae795611a63600198999a966118c196610dd096611820565b9201906119ec565b356104568161048e565b60808301939192611b1061083761083187846115a7565b6080840190611b2861085561083761083185896115a7565b73ffffffffffffffffffffffffffffffffffffffff80921614918215611c18575b611b528461176d565b9788611c04575b88611bd0575b505086611ba6575b5085611b9e575b5084611b8b575b505082611b8157505090565b6104569250611cb8565b611b96929450611cb8565b913880611b75565b945038611b6e565b909550611bb560208301611aef565b90611bc561085560208701611aef565b911614159438611b67565b82985061085561083761094d611bf261083761094d611bf9968b9998996115a7565b958a6115a7565b911614953880611b5f565b9750611c126109738761176d565b97611b59565b915080611c2b6108376108318a876115a7565b161580611c39575b91611b49565b5073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281611c60610837610831868a6115a7565b1614611c33565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561000e570180359067ffffffffffffffff821161000e5760200191813603831361000e57565b90606090611cc960c0840184611c67565b908093918101031261000e57604082013560ff8116810361000e57611d2492611cf460208601611aef565b927fdedf095e8071edfabf29861d428463053c7b5a0a215de0d868c31b4cd566b868936020830135923591612b35565b9081611d76575b81611d34575090565b6104569150610837610831826080611d4d9401906115a7565b73ffffffffffffffffffffffffffffffffffffffff166000526002602052604060002054151590565b9050611d8b61083761094d60808401846115a7565b73ffffffffffffffffffffffffffffffffffffffff16301490611d2b565b9060408201611db881846115a7565b60031015611e46575b60604291013511159283611e15575b505081611dfa575b81611de1575090565b611df49150806040610da19201906115a7565b35101590565b9050611e0c61119c60408301836115a7565b35111590611dd8565b611e209293506115a7565b60041015611e39575b6080429101351015903880611dd0565b611e416115fb565b611e29565b611e4e6115fb565b611dc1565b9260009283915b808310611ebc57505050806040611e729201906115a7565b15611eaf575b358110159182611e8757505090565b611e9791925060408101906115a7565b15611ea25735101590565b611eaa6115fb565b611df4565b611eb76115fb565b611e78565b909193600190611ed0610dd08785876116cb565b9190500194019190611e5a565b909160009283915b808310611f1457505050806040611efd9201906115a7565b15611f0757351490565b611f0f6115fb565b351490565b909193600190611f28610dd08785876116cb565b9190500194019190611ee5565b15611f3c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f746f6b656e49647320646f6e7420696e746572736563740000000000000000006044820152fd5b90918215801561204b575b61204257600092835b858110611fbd57505050501490565b60005b828110611fd1575b50600101611fae565b611fdf6108378285886116cb565b73ffffffffffffffffffffffffffffffffffffffff612005610855610837868c8a6116cb565b91161461201457600101611fc0565b949061203c61203761202c60018095019886896116cb565b610f12848b896116cb565b611f35565b90611fc8565b50505050600190565b508315611fa5565b9190811015612064575b60061b0190565b61206c6115fb565b61205d565b60208101906120808282611719565b91905060208401936120928582611719565b95905083158015612114575b61210957600094855b8781106120b8575050505050501490565b60005b8681106120cc575b506001016120a7565b6120e0816120da8589611719565b90612053565b356120ef836120da8789611719565b35146120fd576001016120bb565b506001968701966120c3565b505050505050600190565b50851561209e565b91907f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811161000e5760051b80928237016000815290565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6080810190811067ffffffffffffffff8211176121a057604052565b6121a8612154565b604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176121a057604052565b9060005b8181106121ff5750505090565b90919260019073ffffffffffffffffffffffffffffffffffffffff85356122258161048e565b168152602090810194019291016121f2565b92919267ffffffffffffffff821161229d575b6040519161228060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601846121ad565b82948184528183011161000e578281602093846000960137010152565b6122a5612154565b61224a565b6122b38161176d565b906124096122e86122c660208401611aef565b6123fd6122d660408601866115a7565b6040519460208601928692849161211c565b039361231a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0958681018352826121ad565b5190209461233461232e60608301836115a7565b906124d4565b9061238361237c61236e61236261234e60808601866115a7565b9290604051928391602083019586916121ee565b038a81018352826121ad565b5190209260a0810190611c67565b3691612237565b6020815191012091604051978895602087019a8b9273ffffffffffffffffffffffffffffffffffffffff60c095929897969360e08601997f7bcfb5a29031e6b8d34ca1a14dd0a1f5cb11b20f755bb2a31ee3c4b143477e4a8752151560208701521660408501526060840152608083015260a08201520152565b039081018352826121ad565b51902090565b60209067ffffffffffffffff8111612429575b60051b0190565b612431612154565b612422565b906124408261240f565b61244d60405191826121ad565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061247b829461240f565b0190602036910137565b602091815181101561249a575b60051b010190565b6124a26115fb565b612492565b805160208092019160005b8281106124c0575050505090565b8351855293810193928101926001016124b2565b906124de81612436565b9160005b82811061252d57505050604051612409816125016020820180956124a7565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018352826121ad565b8061253b60019285856116cb565b356125458161048e565b6125508286866116cb565b6125c361256b61256560209384810190611719565b906125d7565b604080517ff73f37e9f570369ceaab59cef16249ae1c0ad1afd592d656afac0be6f63b87e094810194855273ffffffffffffffffffffffffffffffffffffffff90951660208501528301529091908160608401612501565b5190206125d08287612485565b52016124e2565b906125e181612436565b9160005b82811061260457505050604051612409816125016020820180956124a7565b806126126001928585612053565b35602080612621848888612053565b01356040928351928301937f88f0bd19d14f8b5d22c0605a15d9fffc285ebc8c86fb21139456d305982906f1855283015260609081830152815261266481612184565b5190206126718287612485565b52016125e5565b9060009182915b80831061268c5750505090565b9091926126ae6001916126a86126a3878688611820565b612707565b9061180c565b9301919061267f565b8181106126c2570390565b6126ca6117dc565b0390565b81156126d8570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6040810161271861083182846115a7565b359161272d61272783836115a7565b90611675565b35908184146127bb5761275b61274661199485846115a7565b35612754610d6686856115a7565b35906126b7565b9081156127b457612775610d666127109561277c936115a7565b35426126b7565b90808211156127a357505081905b838181111561279b57030204900390565b900302040190565b836127ae92026126ce565b9061278a565b5050505090565b50505090565b6001548110156127f9575b60016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60190600090565b6128016115fb565b6127cc565b8060005260026020526040600020541560001461289757806001546801000000000000000081101561288a575b600181018060015581101561287d575b7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60155600154906000526002602052604060002055600190565b6128856115fb565b612843565b612892612154565b612833565b50600090565b600154801561290e5760007fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83019280841015612901575b600183520155600155565b6129096115fb565b6128f6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000818152600260205260409020548015612a6c576000918160016129b99310612a5f575b600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff838101928210612a52575b8101908282036129bf575b505050506129a961289d565b6000526002602052604060002090565b55600190565b612a3b927fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf5826129a993612a02951015612a45575b60018a5201549283916127c1565b90919082549060031b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811b9283911b16911916179055565b553880808061299d565b612a4d6115fb565b6129f4565b612a5a6117dc565b612992565b612a676117dc565b612962565b5050600090565b9081602091031261000e57517fffffffff000000000000000000000000000000000000000000000000000000008116810361000e5790565b90929192815260206040818301528351908160408401526000945b828610612b12575050601f817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0926060959611612b05575b0116010190565b6000858286010152612afe565b8581018201518487016060015294810194612ac6565b506040513d6000823e3d90fd5b94612b7f9291949560405193849160208301938490916042927f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201520190565b0392612bb17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0948581018352826121ad565b51902094843b15612cd3579373ffffffffffffffffffffffffffffffffffffffff93612c46602094612c7d946123fd7fffffffff00000000000000000000000000000000000000000000000000000000996040519586938a850191926041937fff00000000000000000000000000000000000000000000000000000000000000928452602084015260f81b1660408201520190565b6040519485809481937f1626ba7e000000000000000000000000000000000000000000000000000000009a8b845260048401612aab565b0392165afa908115612cc6575b600091612c98575b50161490565b612cb9915060203d8111612cbf575b612cb181836121ad565b810190612a73565b38612c92565b503d612ca7565b612cce612b28565b612c8a565b929150612ce09394612dc8565b73ffffffffffffffffffffffffffffffffffffffff90811691161490565b15612d0557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f5369676e61747572653a20496e76616c6964207620706172616d6574657200006044820152fd5b15612d6a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5369676e61747572653a20496e76616c6964207369676e6572000000000000006044820152fd5b9290927f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311612e8557612e3a600093602095612e1460ff8616601b8114908115612e7a575b50612cfe565b604051948594859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa15612e6d575b60005161045673ffffffffffffffffffffffffffffffffffffffff82161515612d63565b612e75612b28565b612e49565b601c91501438612e0e565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f5369676e61747572653a20496e76616c6964207320706172616d6574657200006044820152fdfea2646970667358221220c60af908a2d1daea709ba004d3e35a6a6a02e346b3c411f2fa6b08c2f95450b864736f6c634300080e0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ 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.