Contract Address Details

NEW182LTgek9wwThkznh2UKpePJe4K6MrUDbfpp

NewNFTExchange Last Balance Update: Block #68061637
Created by NEW182Y–V6EA2 at 0x385a–0085ea

Balance

0 AB

Fetching tokens...

Contract name:
NewNFTExchange




Optimization enabled
true
Compiler version
v0.8.3+commit.8d00100c




Optimization runs
200
EVM Version
default

Contract source code

/**
* Submitted for verification at blockscout.com on 2025-04-08 15:10:34.559860Z
*/
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @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
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 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);
}
function _verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) private 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);
}
}
}
}
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
library ArrayUtils {
/**
* Replace bytes in an array with bytes in another array, guarded by a bitmask
* Efficiency of this function is a bit unpredictable because of the EVM's word-specific model (arrays under 32 bytes will be slower)
*
* @dev Mask must be the size of the byte array. A nonzero byte means the byte array can be changed.
* @param array The original array
* @param desired The target array
* @param mask The mask specifying which bits can be changed
* return The updated byte array (the parameter will be modified inplace)
*/
function guardedArrayReplace(bytes memory array, bytes memory desired, bytes memory mask)
internal
pure
{
require(array.length == desired.length);
require(array.length == mask.length);
uint words = array.length / 0x20;
uint index = words * 0x20;
assert(index / 0x20 == words);
uint i;
for (i = 0; i < words; i++) {
/* Conceptually: array[i] = (!mask[i] && array[i]) || (mask[i] && desired[i]), bitwise in word chunks. */
assembly {
let commonIndex := mul(0x20, add(1, i))
let maskValue := mload(add(mask, commonIndex))
mstore(add(array, commonIndex), or(and(not(maskValue), mload(add(array, commonIndex))), and(maskValue, mload(add(desired, commonIndex)))))
}
}
/* Deal with the last section of the byte array. */
if (words > 0) {
/* This overlaps with bytes already set but is still more efficient than iterating through each of the remaining bytes individually. */
i = words;
assembly {
let commonIndex := mul(0x20, add(1, i))
let maskValue := mload(add(mask, commonIndex))
mstore(add(array, commonIndex), or(and(not(maskValue), mload(add(array, commonIndex))), and(maskValue, mload(add(desired, commonIndex)))))
}
} else {
/* If the byte array is shorter than a word, we must unfortunately do the whole thing bytewise.
(bounds checks could still probably be optimized away in assembly, but this is a rare case) */
for (i = index; i < array.length; i++) {
array[i] = ((mask[i] ^ 0xff) & array[i]) | (mask[i] & desired[i]);
}
}
}
/**
* Test if two arrays are equal
* Source: https://github.com/GNSPS/solidity-bytes-utils/blob/master/contracts/BytesLib.sol
*
* @dev Arrays must be of equal length, otherwise will return false
* @param a First array
* @param b Second array
* @return Whether or not all bytes in the arrays are equal
*/
function arrayEq(bytes memory a, bytes memory b)
internal
pure
returns (bool)
{
bool success = true;
assembly {
let length := mload(a)
// if lengths don't match the arrays are not equal
switch eq(length, mload(b))
case 1 {
// cb is a circuit breaker in the for loop since there's
// no said feature for inline assembly loops
// cb = 1 - don't breaker
// cb = 0 - break
let cb := 1
let mc := add(a, 0x20)
let end := add(mc, length)
for {
let cc := add(b, 0x20)
// the next line is the loop condition:
// while(uint(mc < end) + cb == 2)
} eq(add(lt(mc, end), cb), 2) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
// if any of these checks fails then arrays are not equal
if iszero(eq(mload(mc), mload(cc))) {
// unsuccess:
success := 0
cb := 0
}
}
}
default {
// unsuccess:
success := 0
}
}
return success;
}
/**
* Unsafe write byte array into a memory location
*
* @param index Memory location
* @param source Byte array to write
* @return End memory index
*/
function unsafeWriteBytes(uint index, bytes memory source)
internal
pure
returns (uint)
{
if (source.length > 0) {
assembly {
let length := mload(source)
let end := add(source, add(0x20, length))
let arrIndex := add(source, 0x20)
let tempIndex := index
for { } eq(lt(arrIndex, end), 1) {
arrIndex := add(arrIndex, 0x20)
tempIndex := add(tempIndex, 0x20)
} {
mstore(tempIndex, mload(arrIndex))
}
index := add(index, length)
}
}
return index;
}
/**
* Unsafe write address into a memory location
*
* @param index Memory location
* @param source Address to write
* @return End memory index
*/
function unsafeWriteAddress(uint index, address source)
internal
pure
returns (uint)
{
uint conv = uint(uint160(source)) << 0x60;
assembly {
mstore(index, conv)
index := add(index, 0x14)
}
return index;
}
/**
* Unsafe write bytes32 into a memory location
*
* @param index Memory location
* @param source bytes32 to write
* @return End memory index
*/
function unsafeWriteBytes32(uint index, bytes32 source)
internal
pure
returns (uint)
{
assembly {
mstore(index, source)
index := add(index, 0x20)
}
return index;
}
/**
* Unsafe write uint into a memory location
*
* @param index Memory location
* @param source uint to write
* @return End memory index
*/
function unsafeWriteUint(uint index, uint source)
internal
pure
returns (uint)
{
assembly {
mstore(index, source)
index := add(index, 0x20)
}
return index;
}
/**
* Unsafe write uint8 into a memory location
*
* @param index Memory location
* @param source uint8 to write
* @return End memory index
*/
function unsafeWriteUint8(uint index, uint8 source)
internal
pure
returns (uint)
{
assembly {
mstore8(index, source)
index := add(index, 0x1)
}
return index;
}
}
library Orders {
struct Ask {
address signer;
address token;
uint256 tokenId;
uint256 amount;
address strategy;
address currency;
address recipient;
uint256 deadline; // timestamp
address operationalFeeRecipient;
uint8 operationalFeePermil; // max is 255, base is 1000, for operationalFeeRecipient
uint8 referFeePermil; // max is 255, base is 1000, for Bid.referrer
bytes params;
uint256 salt; /* Order salt, used to prevent duplicate hashes. */
uint8 v;
bytes32 r;
bytes32 s;
}
struct Bid {
bytes32 askHash;
address signer;
uint256 amount;
uint256 price;
address recipient;
address referrer;
uint8 v;
bytes32 r;
bytes32 s;
}
/**
* @dev Hash an order ask, returning the canonical order ask hash, without the message prefix
* @param ask Order ask to hash
* @return askHash Hash of order
*/
function hash(Ask memory ask)
internal
pure
returns (bytes32 askHash)
{
/* Unfortunately abi.encodePacked doesn't work here, stack size constraints. */
// address: 0x14 (160)
// uint256(bytes32): 0x20 (256)
// uint8: 0x1 (1)
// address * 6 + uint256 * 4 + uint8 * 2 + params
uint size = (0x14 * 6) + (0x20 * 4) + 2 + ask.params.length;
bytes memory array = new bytes(size);
uint index;
assembly {
index := add(array, 0x20)
}
index = ArrayUtils.unsafeWriteAddress(index, ask.signer);
index = ArrayUtils.unsafeWriteAddress(index, ask.token);
index = ArrayUtils.unsafeWriteUint(index, ask.tokenId);
index = ArrayUtils.unsafeWriteUint(index, ask.amount);
index = ArrayUtils.unsafeWriteAddress(index, ask.strategy);
index = ArrayUtils.unsafeWriteAddress(index, ask.currency);
index = ArrayUtils.unsafeWriteAddress(index, ask.recipient);
index = ArrayUtils.unsafeWriteUint(index, ask.deadline);
index = ArrayUtils.unsafeWriteAddress(index, ask.operationalFeeRecipient);
index = ArrayUtils.unsafeWriteUint8(index, ask.operationalFeePermil);
index = ArrayUtils.unsafeWriteUint8(index, ask.referFeePermil);
index = ArrayUtils.unsafeWriteBytes(index, ask.params);
index = ArrayUtils.unsafeWriteUint(index, ask.salt);
assembly {
askHash := keccak256(add(array, 0x20), size)
}
return askHash;
}
function hash(Bid memory bid) internal pure returns (bytes32) {
return
keccak256(
abi.encodePacked(bid.askHash, bid.signer, bid.amount, bid.price, bid.recipient, bid.referrer)
);
}
}
/**
* @dev Interface of the Registrar.
*/
interface IRegistrar {
/**
* @dev updateRoyaltyFeeInfo.
*
* update the `recipient` and `permit` for `token`.
* - the max value of permit is 255, the base is 1000
*
*/
function updateRoyaltyFeeInfo(address token, address recipient, uint8 permit) external returns (bool);
/**
* @dev Returns the `recipient` and `permit` of `token`.
*
*/
function royaltyFeeInfo(address token) external view returns (address recipient, uint8 permil);
/**
* @dev Emitted when `updateRoyaltyFeeInfo` called.
*
* Note that `value` may be zero.
*/
event Updated(address indexed token, address indexed recipient, uint8 indexed permit, address owner);
}
//
interface IOrderBook {
event SubmitOrder(bytes32 indexed hash, Orders.Ask order);
function getOrderBaseInfo(bytes32 hash)
external
view
returns (
address signer,
address nft,
uint256 tokenId,
uint256 amount,
address strategy,
address currency,
address recipient,
uint256 deadline,
address operationalFeeRecipient,
uint8 operationalFeePermil,
uint8 referFeePermil,
bytes memory params
);
function getOrderExInfo(bytes32 hash) external view returns (
uint256 salt,
uint8 v,
bytes32 r,
bytes32 s
);
function submitOrder(
address nft,
uint256 tokenId,
uint256 amount,
address strategy,
address currency,
address recipient,
uint256 deadline,
address operationalFeeRecipient,// address[] memory addrs, //
uint8[] memory permils,
// uint8 operationalFeePermil,
// uint8 referFeePermil, // uint8[] memory permils, //
bytes memory params,
uint256 salt
) external returns (bytes32 hash);
}
interface IStrategy {
function canClaim(
uint256 deadline,
bytes memory params,
address bidder,
uint256 bidPrice,
address bestBidder,
uint256 bestBidPrice,
uint256 bestBidBlock
) external view returns (bool);
function canBid(
uint256 deadline,
bytes memory params,
address bidder,
uint256 bidPrice,
address bestBidder,
uint256 bestBidPrice,
uint256 bestBidBlock
) external view returns (bool);
function canCancel(
uint256 deadline,
bytes memory params,
address bidder,
uint256 bidPrice,
address bestBidder,
uint256 bestBidPrice,
uint256 bestBidBlock
) external view returns (bool);
}
interface IBaseExchange {
event Cancel(bytes32 indexed hash);
event Claim(
bytes32 indexed hash,
address bidder,
uint256 amount,
uint256 price,
address recipient,
address referrer
);
event Bid(bytes32 indexed hash, address bidder, uint256 amount, uint256 price, address recipient, address referrer);
event Withdraw(
bytes32 indexed hash,
uint256 amount
);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function isStrategyWhitelisted(address strategy) external view returns(bool);
function protocolFeeInfo() external view returns (address recipient, uint8 permil);
function royaltyFeeInfo(address nft) external view returns (address recipient, uint8 permil);
function bestBid(bytes32 hash)
external
view
returns (
address bidder,
uint256 amount,
uint256 price,
address recipient,
address referrer,
uint256 blockNumber
);
function isCancelledOrClaimed(bytes32 hash) external view returns (bool);
function amountFilled(bytes32 hash) external view returns (uint256);
function cancel(Orders.Ask memory order) external;
function cancelByHash(bytes32 askHash) external;
function bidByOrders(Orders.Ask memory askOrder, Orders.Bid memory bidOrder) external payable returns (bool executed);
function bid(
Orders.Ask memory askOrder,
uint256 bidAmount,
uint256 bidPrice,
address bidRecipient,
address bidReferrer
) external payable returns (bool executed);
function bidByHash(
bytes32 askHash,
uint256 bidAmount,
uint256 bidPrice,
address bidRecipient,
address bidReferrer
) external payable returns (bool executed);
// for `canBid`, such as `EnglishAuction`
function claim(Orders.Ask memory order) external payable;
function claimByHash(bytes32 askHash) external payable;
}
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}
/*
* @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;
}
}
/**
* @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() {
_setOwner(_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 {
_setOwner(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");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
/// @title Interface for verifying contract-based account signatures
/// @notice Interface that verifies provided signature for the data
/// @dev Interface defined by EIP-1271
interface IERC1271 {
/// @notice Returns whether the provided signature is valid for the provided data
/// @dev MUST return the bytes4 magic value 0x1626ba7e when function passes.
/// MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5).
/// MUST allow external calls.
/// @param hash Hash of the data to be signed
/// @param signature Signature byte array associated with _data
/// @return magicValue The bytes4 magic value 0x1626ba7e
function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(_initializing || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
}
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardInitializable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal initializer {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal initializer {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "SHOYU: REENTRANT");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}
abstract contract BaseExchange is ReentrancyGuardInitializable, IBaseExchange, IOrderBook {
using SafeMath for uint256;
using SafeERC20 for IERC20;
using Orders for Orders.Ask;
using Orders for Orders.Bid;
mapping(bytes32 => Orders.Ask) private _orders;
struct BestBid {
address bidder;
uint256 amount;
uint256 price;
address recipient;
address referrer;
uint256 blockNumber;
}
mapping(bytes32 => BestBid) public override bestBid;
mapping(bytes32 => bool) public override isCancelledOrClaimed;
mapping(bytes32 => uint256) public override amountFilled;
struct Fees {
address token;
address currency;
address from;
address to;
uint256 amount;
address operationalFeeRecipient;
uint8 operationalFeePermil;
address referrer;
uint8 referFeePermil;
}
function __BaseNFTExchange_init() internal {
__ReentrancyGuard_init();
}
function DOMAIN_SEPARATOR() public view virtual override returns (bytes32);
function isStrategyWhitelisted(address strategy) public view virtual override returns(bool);
function protocolFeeInfo() public view virtual override returns (address recipient, uint8 permil);
function royaltyFeeInfo(address token) public view virtual override returns (address recipient, uint8 permil) {
return (token, uint8(0));
}
function _transfer(
address token,
address from,
address to,
uint256 tokenId,
uint256 amount
) internal virtual;
function cancel(Orders.Ask memory order) external override {
require(order.signer == msg.sender, "BaseExchange: FORBIDDEN");
bytes32 hash = order.hash();
BestBid storage best = bestBid[hash];
require(IStrategy(order.strategy).canCancel(
order.deadline,
order.params,
best.bidder,
best.price,
best.bidder,
best.price,
best.blockNumber
), "BaseExchange: CAN_NOT_CANCEL");
isCancelledOrClaimed[hash] = true;
emit Cancel(hash);
}
function cancelByHash(bytes32 askHash) external override {
Orders.Ask memory order = _orders[askHash];
require(order.signer == msg.sender, "BaseExchange: FORBIDDEN");
require(askHash == order.hash(), "BaseExchange: HASH_NOT_MATCH");
BestBid storage best = bestBid[askHash];
require(IStrategy(order.strategy).canCancel(
order.deadline,
order.params,
best.bidder,
best.price,
best.bidder,
best.price,
best.blockNumber
), "BaseExchange: CAN_NOT_CANCEL");
isCancelledOrClaimed[askHash] = true;
emit Cancel(askHash);
}
function bidByOrders(Orders.Ask memory askOrder, Orders.Bid memory bidOrder)
external
payable
override
nonReentrant
returns (bool executed)
{
bytes32 askHash = askOrder.hash();
require(askHash == bidOrder.askHash, "BaseExchange: UNMATCHED_HASH");
require(bidOrder.signer != address(0), "BaseExchange: INVALID_SIGNER");
_verify(bidOrder.hash(), bidOrder.signer, bidOrder.v, bidOrder.r, bidOrder.s);
_verify(askHash, askOrder.signer, askOrder.v, askOrder.r, askOrder.s);
return
_bid(
askOrder,
askHash,
bidOrder.signer,
bidOrder.amount,
bidOrder.price,
bidOrder.recipient,
bidOrder.referrer
);
}
function bid(
Orders.Ask memory askOrder,
uint256 bidAmount,
uint256 bidPrice,
address bidRecipient,
address bidReferrer
) external payable override nonReentrant returns (bool executed) {
bytes32 askHash = askOrder.hash();
_verify(askHash, askOrder.signer, askOrder.v, askOrder.r, askOrder.s);
return _bid(askOrder, askHash, msg.sender, bidAmount, bidPrice, bidRecipient, bidReferrer);
}
function bidByHash(
bytes32 askHash,
uint256 bidAmount,
uint256 bidPrice,
address bidRecipient,
address bidReferrer
) external payable override nonReentrant returns (bool executed) {
Orders.Ask memory askOrder = _orders[askHash];
require(askHash == askOrder.hash(), "BaseExchange: UNMATCHED_ASK_ORDER_HASH");
return _bid(askOrder, askHash, msg.sender, bidAmount, bidPrice, bidRecipient, bidReferrer);
}
function _bid(
Orders.Ask memory askOrder,
bytes32 askHash,
address bidder,
uint256 bidAmount,
uint256 bidPrice,
address bidRecipient,
address bidReferrer
) internal returns (bool executed) {
require(bidAmount > 0, "BaseExchange: INVALID_AMOUNT");
require(amountFilled[askHash].add(bidAmount) <= askOrder.amount, "BaseExchange: SOLD_OUT");
_validate(askOrder, askHash);
BestBid storage best = bestBid[askHash];
if (IStrategy(askOrder.strategy).canClaim(
askOrder.deadline,
askOrder.params,
bidder,
bidPrice,
best.bidder,
best.price,
best.blockNumber)
) {
amountFilled[askHash] = amountFilled[askHash].add(bidAmount);
address recipient = askOrder.recipient;
if (recipient == address(0)) recipient = askOrder.signer;
Fees memory fee = Fees(askOrder.token, askOrder.currency, bidder, recipient, bidPrice * bidAmount,
askOrder.operationalFeeRecipient, askOrder.operationalFeePermil,
bidReferrer, askOrder.referFeePermil);
require(
_transferFeesAndFunds(fee),
"BaseExchange: FAILED_TO_TRANSFER_FUNDS"
);
if (bidRecipient == address(0)) bidRecipient = bidder;
_transfer(askOrder.token, askOrder.signer, bidRecipient, askOrder.tokenId, bidAmount);
emit Claim(askHash, bidder, bidAmount, bidPrice, bidRecipient, bidReferrer);
return true;
} else {
if (
IStrategy(askOrder.strategy).canBid(
askOrder.deadline,
askOrder.params,
bidder,
bidPrice,
best.bidder,
best.price,
best.blockNumber
)
) {
best.bidder = bidder;
best.amount = bidAmount;
best.price = bidPrice;
best.recipient = bidRecipient;
best.referrer = bidReferrer;
best.blockNumber = block.number;
emit Bid(askHash, bidder, bidAmount, bidPrice, bidRecipient, bidReferrer);
return false;
}
}
revert("BaseExchange: FAILURE");
}
function claim(Orders.Ask memory askOrder) external payable override nonReentrant {
bytes32 askHash = askOrder.hash();
_verify(askHash, askOrder.signer, askOrder.v, askOrder.r, askOrder.s);
_claim(askOrder, askHash);
}
function claimByHash(
bytes32 askHash
) external payable override nonReentrant {
Orders.Ask memory askOrder = _orders[askHash];
require(askHash == askOrder.hash(), "BaseExchange: UNMATCHED_ASK_ORDER_HASH");
_claim(askOrder, askHash);
}
function _claim(Orders.Ask memory askOrder, bytes32 askHash) internal {
_validate(askOrder, askHash);
BestBid memory best = bestBid[askHash];
require(
IStrategy(askOrder.strategy).canClaim(
askOrder.deadline,
askOrder.params,
best.bidder,
best.price,
best.bidder,
best.price,
best.blockNumber
),
"BaseExchange: FAILURE"
);
address recipient = askOrder.recipient;
if (recipient == address(0)) recipient = askOrder.signer;
isCancelledOrClaimed[askHash] = true;
Fees memory fee = Fees(askOrder.token, askOrder.currency, best.bidder, recipient, best.price * best.amount,
askOrder.operationalFeeRecipient, askOrder.operationalFeePermil,
best.referrer, askOrder.referFeePermil);
require(_transferFeesAndFunds(fee), "BaseExchange: FAILED_TO_TRANSFER_FUNDS");
amountFilled[askHash] = amountFilled[askHash].add(best.amount);
address bidRecipient = best.recipient;
if (bidRecipient == address(0)) bidRecipient = best.bidder;
_transfer(askOrder.token, askOrder.signer, bidRecipient, askOrder.tokenId, best.amount);
delete bestBid[askHash];
emit Claim(askHash, best.bidder, best.amount, best.price, bidRecipient, best.referrer);
}
function submitOrder(
address nft,
uint256 tokenId,
uint256 amount,
address strategy,
address currency,
address recipient,
uint256 deadline,
address operationalFeeRecipient,
uint8[] memory permils, // operationalFeePermil, referFeePermil
bytes memory params,
uint256 salt
) external override nonReentrant returns (bytes32 hash) {
Orders.Ask memory order =
Orders.Ask(
msg.sender,
nft,
tokenId,
amount,
strategy,
currency,
recipient,
deadline,
operationalFeeRecipient,
permils[0],
permils[1],
params,
salt,
0,
bytes32(0),
bytes32(0)
);
hash = order.hash();
_orders[hash] = order;
emit SubmitOrder(hash, order);
}
function getOrderBaseInfo(bytes32 hash)
public
override
view
returns (
address signer,
address nft,
uint256 tokenId,
uint256 amount,
address strategy,
address currency,
address recipient,
uint256 deadline,
address operationalFeeRecipient,
uint8 operationalFeePermil,
uint8 referFeePermil,
bytes memory params
) {
Orders.Ask memory ask = _orders[hash];
return (
ask.signer,
ask.token,
ask.tokenId,
ask.amount,
ask.strategy,
ask.currency,
ask.recipient,
ask.deadline,
ask.operationalFeeRecipient,
ask.operationalFeePermil,
ask.referFeePermil,
ask.params
);
}
function getOrderExInfo(bytes32 hash) public override view returns (
uint256 salt,
uint8 v,
bytes32 r,
bytes32 s
) {
Orders.Ask memory ask = _orders[hash];
return (
ask.salt,
ask.v,
ask.r,
ask.s
);
}
function _validate(Orders.Ask memory askOrder, bytes32 askHash) internal view {
require(!isCancelledOrClaimed[askHash], "BaseExchange: CANCELLED");
require(askOrder.signer != address(0), "BaseExchange: INVALID_MAKER");
require(askOrder.token != address(0), "BaseExchange: INVALID_NFT");
require(askOrder.amount > 0, "BaseExchange: INVALID_AMOUNT");
require(askOrder.strategy != address(0), "BaseExchange: INVALID_STRATEGY");
// require(askOrder.currency != address(0), "BaseExchange: INVALID_CURRENCY");
require(isStrategyWhitelisted(askOrder.strategy), "BaseExchange: STRATEGY_NOT_WHITELISTED");
}
function _verify(
bytes32 hash,
address signer,
uint8 v,
bytes32 r,
bytes32 s
) internal view {
bytes32 digest = keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), hash));
if (Address.isContract(signer)) {
require(
IERC1271(signer).isValidSignature(digest, abi.encodePacked(r, s, v)) == 0x1626ba7e,
"BaseExchange: UNAUTHORIZED"
);
} else {
require(ecrecover(digest, v, r, s) == signer, "BaseExchange: UNAUTHORIZED");
}
}
function _transferFeesAndFunds(
Fees memory fee
) internal returns (bool) {
if (fee.currency == address(0)) {
if (fee.amount != msg.value) {
return false;
}
uint256 remainder = fee.amount;
(address protocolFeeRecipient, uint8 protocolFeePermil) = protocolFeeInfo();
if (protocolFeeRecipient != address(0)) {
uint256 protocolFeeAmount = (fee.amount * protocolFeePermil) / 1000;
if (protocolFeeAmount > 0) {
Address.sendValue(payable(protocolFeeRecipient), protocolFeeAmount);
remainder -= protocolFeeAmount;
}
}
if (fee.operationalFeeRecipient != address(0)) {
uint256 operationalFeeAmount = (fee.amount * fee.operationalFeePermil) / 1000;
if (operationalFeeAmount > 0) {
Address.sendValue(payable(fee.operationalFeeRecipient), operationalFeeAmount);
remainder -= operationalFeeAmount;
}
}
(address royaltyFeeRecipient, uint8 royaltyFeePermil) = royaltyFeeInfo(fee.token);
if (royaltyFeeRecipient != address(0)) {
if (royaltyFeePermil != type(uint8).max) {
uint256 royaltyFeeAmount = (fee.amount * royaltyFeePermil) / 1000;
if (royaltyFeeAmount > 0) {
remainder -= royaltyFeeAmount;
Address.sendValue(payable(royaltyFeeRecipient), royaltyFeeAmount);
}
}
}
if (fee.referrer != address(0)) {
uint256 referFeeAmount = (fee.amount * fee.referFeePermil) / 1000;
if (referFeeAmount > 0) {
Address.sendValue(payable(fee.referrer), referFeeAmount);
remainder -= referFeeAmount;
}
}
Address.sendValue(payable(fee.to), remainder);
return true;
} else {
if (!_safeTransferFrom(fee.currency, fee.from, address(this), fee.amount)) {
return false;
}
uint256 remainder = fee.amount;
(address protocolFeeRecipient, uint8 protocolFeePermil) = protocolFeeInfo();
if (protocolFeeRecipient != address(0)) {
uint256 protocolFeeAmount = (fee.amount * protocolFeePermil) / 1000;
if (protocolFeeAmount > 0) {
IERC20(fee.currency).safeTransfer(protocolFeeRecipient, protocolFeeAmount);
remainder -= protocolFeeAmount;
}
}
if (fee.operationalFeeRecipient != address(0)) {
uint256 operationalFeeAmount = (fee.amount * fee.operationalFeePermil) / 1000;
if (operationalFeeAmount > 0) {
IERC20(fee.currency).safeTransfer(fee.operationalFeeRecipient, operationalFeeAmount);
remainder -= operationalFeeAmount;
}
}
(address royaltyFeeRecipient, uint8 royaltyFeePermil) = royaltyFeeInfo(fee.token);
if (royaltyFeeRecipient != address(0)) {
if (royaltyFeePermil != type(uint8).max) {
uint256 royaltyFeeAmount = (fee.amount * royaltyFeePermil) / 1000;
if (royaltyFeeAmount > 0) {
remainder -= royaltyFeeAmount;
IERC20(fee.currency).safeTransfer(royaltyFeeRecipient, royaltyFeeAmount);
}
}
}
if (fee.referrer != address(0)) {
uint256 referFeeAmount = (fee.amount * fee.referFeePermil) / 1000;
if (referFeeAmount > 0) {
IERC20(fee.currency).safeTransfer(fee.referrer, referFeeAmount);
remainder -= referFeeAmount;
}
}
IERC20(fee.currency).safeTransfer(fee.to, remainder);
return true;
}
}
function _safeTransferFrom(
address token,
address from,
address to,
uint256 value
) private returns (bool) {
(bool success, bytes memory returndata) =
token.call(abi.encodeWithSelector(IERC20(token).transferFrom.selector, from, to, value));
return success && (returndata.length == 0 || abi.decode(returndata, (bool)));
}
}
/**
* @dev {Registrar} token, including:
*
* - store info by verify owner
* - mint token ID
*/
abstract contract Registrar is Ownable, IRegistrar {
bytes4 public constant OwnerSelector = bytes4(keccak256("owner()")); // 0x8da5cb5b
bytes public constant OwnerData = abi.encodeWithSelector(OwnerSelector);
mapping (address => address) private _recipients;
mapping (address => uint8) private _permils;
function isReceiptOwner(address owner, address target) public view returns (bool) {
if (target == owner) {
return true;
}
if (Address.isContract(target)) {
// refer Address.functionStaticCall(target, OwnerData);
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(OwnerData);
if (success) {
address targetOwner = abi.decode(returndata, (address));
if (targetOwner == owner) {
return true;
}
}
}
return false;
}
/**
* @dev Throws if called by any account other than the owner of the target token and the DAO.
*/
modifier onlyTokenOwner(address target) {
require(isReceiptOwner(_msgSender(), target) || _msgSender() == owner(), "Registrar: caller is not the owner of target");
_;
}
function royaltyFeeInfo(address token) public view override virtual returns (address recipient, uint8 permil) {
return (_recipients[token], _permils[token]);
}
function updateRoyaltyFeeInfo(address token, address recipient, uint8 permit) override virtual onlyTokenOwner(token) public returns (bool) {
_recipients[token] = recipient;
_permils[token] = permit;
emit Updated(token, recipient, permit, _msgSender());
return true;
}
}
contract NewNFTExchange is BaseExchange, Ownable, Registrar {
bytes32 internal immutable _DOMAIN_SEPARATOR;
address internal _protocolFeeRecipient;
uint8 internal _protocolFeePermil; // out of 1000
mapping(address => bool) private _isStrategyWhitelisted;
constructor() {
__BaseNFTExchange_init();
uint256 chainId;
assembly {
chainId := chainid()
}
_DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256("NewNFTExchange"),
keccak256(bytes("1")),
chainId,
address(this)
)
);
}
function DOMAIN_SEPARATOR() public view override returns (bytes32) {
return _DOMAIN_SEPARATOR;
}
function _transfer(
address nft,
address from,
address to,
uint256 tokenId,
uint256 amount
) internal override {
if (IERC165(nft).supportsInterface(0x80ac58cd)) {
IERC721(nft).safeTransferFrom(from, to, tokenId);
} else if (IERC165(nft).supportsInterface(0xd9b67a26)) {
IERC1155(nft).safeTransferFrom(from, to, tokenId, amount, "");
} else {
// revert
revert("NewNFTExchange: unsupported token");
}
}
function isStrategyWhitelisted(address strategy) public view override returns(bool) {
return _isStrategyWhitelisted[strategy];
}
function setStrategyWhitelisted(address strategy, bool whitelisted) public onlyOwner {
require(strategy != address(0), "NewNFTExchange: INVALID_SALE");
_isStrategyWhitelisted[strategy] = whitelisted;
}
function protocolFeeInfo() public view override returns (address recipient, uint8 permil) {
return (_protocolFeeRecipient, _protocolFeePermil);
}
// This function should be called by a multi-sig `owner`, not an EOA
function setProtocolInfo(address recipient, uint8 permil) external onlyOwner {
_protocolFeeRecipient = recipient;
_protocolFeePermil = permil;
}
function royaltyFeeInfo(address token) public view override(BaseExchange, Registrar) returns (address recipient, uint8 permil) {
return Registrar.royaltyFeeInfo(token);
}
}

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"Bid","inputs":[{"type":"bytes32","name":"hash","internalType":"bytes32","indexed":true},{"type":"address","name":"bidder","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"price","internalType":"uint256","indexed":false},{"type":"address","name":"recipient","internalType":"address","indexed":false},{"type":"address","name":"referrer","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Cancel","inputs":[{"type":"bytes32","name":"hash","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"event","name":"Claim","inputs":[{"type":"bytes32","name":"hash","internalType":"bytes32","indexed":true},{"type":"address","name":"bidder","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"price","internalType":"uint256","indexed":false},{"type":"address","name":"recipient","internalType":"address","indexed":false},{"type":"address","name":"referrer","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"SubmitOrder","inputs":[{"type":"bytes32","name":"hash","internalType":"bytes32","indexed":true},{"type":"tuple","name":"order","internalType":"struct Orders.Ask","indexed":false,"components":[{"type":"address","name":"signer","internalType":"address"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"strategy","internalType":"address"},{"type":"address","name":"currency","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"address","name":"operationalFeeRecipient","internalType":"address"},{"type":"uint8","name":"operationalFeePermil","internalType":"uint8"},{"type":"uint8","name":"referFeePermil","internalType":"uint8"},{"type":"bytes","name":"params","internalType":"bytes"},{"type":"uint256","name":"salt","internalType":"uint256"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]}],"anonymous":false},{"type":"event","name":"Updated","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"address","name":"recipient","internalType":"address","indexed":true},{"type":"uint8","name":"permit","internalType":"uint8","indexed":true},{"type":"address","name":"owner","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Withdraw","inputs":[{"type":"bytes32","name":"hash","internalType":"bytes32","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"DOMAIN_SEPARATOR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"OwnerData","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"OwnerSelector","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"amountFilled","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"bidder","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"address","name":"recipient","internalType":"address"},{"type":"address","name":"referrer","internalType":"address"},{"type":"uint256","name":"blockNumber","internalType":"uint256"}],"name":"bestBid","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"bool","name":"executed","internalType":"bool"}],"name":"bid","inputs":[{"type":"tuple","name":"askOrder","internalType":"struct Orders.Ask","components":[{"type":"address","name":"signer","internalType":"address"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"strategy","internalType":"address"},{"type":"address","name":"currency","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"address","name":"operationalFeeRecipient","internalType":"address"},{"type":"uint8","name":"operationalFeePermil","internalType":"uint8"},{"type":"uint8","name":"referFeePermil","internalType":"uint8"},{"type":"bytes","name":"params","internalType":"bytes"},{"type":"uint256","name":"salt","internalType":"uint256"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]},{"type":"uint256","name":"bidAmount","internalType":"uint256"},{"type":"uint256","name":"bidPrice","internalType":"uint256"},{"type":"address","name":"bidRecipient","internalType":"address"},{"type":"address","name":"bidReferrer","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"bool","name":"executed","internalType":"bool"}],"name":"bidByHash","inputs":[{"type":"bytes32","name":"askHash","internalType":"bytes32"},{"type":"uint256","name":"bidAmount","internalType":"uint256"},{"type":"uint256","name":"bidPrice","internalType":"uint256"},{"type":"address","name":"bidRecipient","internalType":"address"},{"type":"address","name":"bidReferrer","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"bool","name":"executed","internalType":"bool"}],"name":"bidByOrders","inputs":[{"type":"tuple","name":"askOrder","internalType":"struct Orders.Ask","components":[{"type":"address","name":"signer","internalType":"address"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"strategy","internalType":"address"},{"type":"address","name":"currency","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"address","name":"operationalFeeRecipient","internalType":"address"},{"type":"uint8","name":"operationalFeePermil","internalType":"uint8"},{"type":"uint8","name":"referFeePermil","internalType":"uint8"},{"type":"bytes","name":"params","internalType":"bytes"},{"type":"uint256","name":"salt","internalType":"uint256"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]},{"type":"tuple","name":"bidOrder","internalType":"struct Orders.Bid","components":[{"type":"bytes32","name":"askHash","internalType":"bytes32"},{"type":"address","name":"signer","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"address","name":"recipient","internalType":"address"},{"type":"address","name":"referrer","internalType":"address"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancel","inputs":[{"type":"tuple","name":"order","internalType":"struct Orders.Ask","components":[{"type":"address","name":"signer","internalType":"address"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"strategy","internalType":"address"},{"type":"address","name":"currency","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"address","name":"operationalFeeRecipient","internalType":"address"},{"type":"uint8","name":"operationalFeePermil","internalType":"uint8"},{"type":"uint8","name":"referFeePermil","internalType":"uint8"},{"type":"bytes","name":"params","internalType":"bytes"},{"type":"uint256","name":"salt","internalType":"uint256"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelByHash","inputs":[{"type":"bytes32","name":"askHash","internalType":"bytes32"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"claim","inputs":[{"type":"tuple","name":"askOrder","internalType":"struct Orders.Ask","components":[{"type":"address","name":"signer","internalType":"address"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"strategy","internalType":"address"},{"type":"address","name":"currency","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"address","name":"operationalFeeRecipient","internalType":"address"},{"type":"uint8","name":"operationalFeePermil","internalType":"uint8"},{"type":"uint8","name":"referFeePermil","internalType":"uint8"},{"type":"bytes","name":"params","internalType":"bytes"},{"type":"uint256","name":"salt","internalType":"uint256"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"claimByHash","inputs":[{"type":"bytes32","name":"askHash","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"signer","internalType":"address"},{"type":"address","name":"nft","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"strategy","internalType":"address"},{"type":"address","name":"currency","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"address","name":"operationalFeeRecipient","internalType":"address"},{"type":"uint8","name":"operationalFeePermil","internalType":"uint8"},{"type":"uint8","name":"referFeePermil","internalType":"uint8"},{"type":"bytes","name":"params","internalType":"bytes"}],"name":"getOrderBaseInfo","inputs":[{"type":"bytes32","name":"hash","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"salt","internalType":"uint256"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}],"name":"getOrderExInfo","inputs":[{"type":"bytes32","name":"hash","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isCancelledOrClaimed","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isReceiptOwner","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"target","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isStrategyWhitelisted","inputs":[{"type":"address","name":"strategy","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"recipient","internalType":"address"},{"type":"uint8","name":"permil","internalType":"uint8"}],"name":"protocolFeeInfo","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"recipient","internalType":"address"},{"type":"uint8","name":"permil","internalType":"uint8"}],"name":"royaltyFeeInfo","inputs":[{"type":"address","name":"token","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setProtocolInfo","inputs":[{"type":"address","name":"recipient","internalType":"address"},{"type":"uint8","name":"permil","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setStrategyWhitelisted","inputs":[{"type":"address","name":"strategy","internalType":"address"},{"type":"bool","name":"whitelisted","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes32","name":"hash","internalType":"bytes32"}],"name":"submitOrder","inputs":[{"type":"address","name":"nft","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"strategy","internalType":"address"},{"type":"address","name":"currency","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"address","name":"operationalFeeRecipient","internalType":"address"},{"type":"uint8[]","name":"permils","internalType":"uint8[]"},{"type":"bytes","name":"params","internalType":"bytes"},{"type":"uint256","name":"salt","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"updateRoyaltyFeeInfo","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint8","name":"permit","internalType":"uint8"}]}]
            

Contract Byte Code

0x6080604052600436106101815760003560e01c80635eba102a116100d1578063999ba27c1161008a578063b8208c6711610064578063b8208c6714610553578063ba87fbe71461058b578063e331a715146105ab578063f2fde38b146105db57610181565b8063999ba27c1461050b578063aec0b5431461052b578063b35f33011461054057610181565b80635eba102a146103fe5780636df2189c1461043f578063715018a61461048157806375e6590f14610496578063823f3b3c146104c35780638da5cb5b146104e357610181565b8063224032a61161013e5780633644e515116101185780633644e515146102ed5780633c19e2f61461032a5780634e3a37be1461033d5780635771f9971461035d57610181565b8063224032a61461026d57806324b72fd9146102805780633334998c146102a057610181565b806305609acc146101865780630820bc02146101a85780630de9f1bf146101c85780630e041606146101fd5780631bac15e0146102105780632055beda1461025a575b600080fd5b34801561019257600080fd5b506101a66101a13660046139be565b6105fb565b005b3480156101b457600080fd5b506101a66101c3366004613aa3565b61065d565b3480156101d457600080fd5b506101e86101e3366004613868565b610800565b60405190151581526020015b60405180910390f35b6101e861020b366004613ba9565b61091a565b34801561021c57600080fd5b506040805160048152602481019091526020810180516001600160e01b0316638da5cb5b60e01b17905261024d9081565b6040516101f49190613d1c565b6101a6610268366004613aa3565b61098f565b6101a661027b366004613a0e565b6109f6565b34801561028c57600080fd5b506101a661029b3660046138ae565b610bbe565b3480156102ac57600080fd5b506102d47f8da5cb5b36e7f68c1d2e56001220cdbdd3ba2616072f718acfda4a06441a807d81565b6040516001600160e01b031990911681526020016101f4565b3480156102f957600080fd5b507f5db69c81c664d97f8caf39ff79c2a9f0503ecac2939aeef98292e01de7e687a15b6040519081526020016101f4565b6101e8610338366004613ad6565b610c69565b34801561034957600080fd5b506101e8610358366004613830565b610dc0565b34801561036957600080fd5b506103bf610378366004613a0e565b60036020819052600091825260409091208054600182015460028301549383015460048401546005909401546001600160a01b039384169592949293918216929091169086565b604080516001600160a01b03978816815260208101969096528501939093529084166060840152909216608082015260a081019190915260c0016101f4565b34801561040a57600080fd5b5061041e6104193660046137f8565b610ec6565b604080516001600160a01b03909316835260ff9091166020830152016101f4565b34801561044b57600080fd5b5061045f61045a366004613a0e565b610ef7565b6040805194855260ff90931660208501529183015260608201526080016101f4565b34801561048d57600080fd5b506101a6611096565b3480156104a257600080fd5b5061031c6104b1366004613a0e565b60056020526000908152604090205481565b3480156104cf57600080fd5b506101a66104de366004613a0e565b6110cc565b3480156104ef57600080fd5b506006546040516001600160a01b0390911681526020016101f4565b34801561051757600080fd5b506101e86105263660046137f8565b61142a565b34801561053757600080fd5b5061041e61144c565b6101e861054e366004613a26565b611468565b34801561055f57600080fd5b5061057361056e366004613a0e565b611637565b6040516101f49c9b9a99989796959493929190613c49565b34801561059757600080fd5b5061031c6105a63660046138db565b61183c565b3480156105b757600080fd5b506101e86105c6366004613a0e565b60046020526000908152604090205460ff1681565b3480156105e757600080fd5b506101a66105f63660046137f8565b611b12565b6006546001600160a01b0316331461062e5760405162461bcd60e51b815260040161062590613d9f565b60405180910390fd5b6009805460ff909216600160a01b026001600160a81b03199092166001600160a01b0390931692909217179055565b80516001600160a01b031633146106b05760405162461bcd60e51b81526020600482015260176024820152762130b9b2a2bc31b430b733b29d102327a92124a22222a760491b6044820152606401610625565b60006106bb82611bad565b60008181526003602052604090819020608085015160e08601516101608701518354600285015460058601549651632546b5a560e01b815297985094966001600160a01b0394851696632546b5a59661071f96909316929183918391600401613f5b565b60206040518083038186803b15801561073757600080fd5b505afa15801561074b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076f91906139f2565b6107bb5760405162461bcd60e51b815260206004820152601c60248201527f4261736545786368616e67653a2043414e5f4e4f545f43414e43454c000000006044820152606401610625565b600082815260046020526040808220805460ff191660011790555183917fe8d9861dbc9c663ed3accd261bbe2fe01e0d3d9e5f51fa38523b265c7757a93a91a2505050565b60008361080d3382610dc0565b8061082257506006546001600160a01b031633145b6108835760405162461bcd60e51b815260206004820152602c60248201527f5265676973747261723a2063616c6c6572206973206e6f7420746865206f776e60448201526b195c881bd9881d185c99d95d60a21b6064820152608401610625565b6001600160a01b03858116600081815260076020908152604080832080546001600160a01b031916958a16958617905560089091529020805460ff191660ff871690811790915591907f1e313ca8f99baa3c5d994acdda88e3b8d9033a95e985df6953e5f9b13c7d767e6108f43390565b6040516001600160a01b03909116815260200160405180910390a4506001949350505050565b60006002600154141561093f5760405162461bcd60e51b815260040161062590613d2f565b6002600155600061094f87611bad565b9050610971818860000151896101a001518a6101c001518b6101e00151611cea565b61098087823389898989611f2f565b60018055979650505050505050565b600260015414156109b25760405162461bcd60e51b815260040161062590613d2f565b600260015560006109c282611bad565b90506109e4818360000151846101a00151856101c00151866101e00151611cea565b6109ee82826123db565b505060018055565b60026001541415610a195760405162461bcd60e51b815260040161062590613d2f565b6002600181815560008381526020838152604080832081516102008101835281546001600160a01b039081168252958201548616938101939093529485015490820152600384015460608201526004840154831660808201526005840154831660a08201526006840154831660c0820152600784015460e0820152600884015492831661010082015260ff600160a01b84048116610120830152600160a81b90930490921661014083015260098301805491939161016084019190610add90614077565b80601f0160208091040260200160405190810160405280929190818152602001828054610b0990614077565b8015610b565780601f10610b2b57610100808354040283529160200191610b56565b820191906000526020600020905b815481529060010190602001808311610b3957829003601f168201915b5050509183525050600a8201546020820152600b82015460ff166040820152600c8201546060820152600d909101546080909101529050610b9681611bad565b8214610bb45760405162461bcd60e51b815260040161062590613dd4565b6109ee81836123db565b6006546001600160a01b03163314610be85760405162461bcd60e51b815260040161062590613d9f565b6001600160a01b038216610c3e5760405162461bcd60e51b815260206004820152601c60248201527f4e65774e465445786368616e67653a20494e56414c49445f53414c45000000006044820152606401610625565b6001600160a01b03919091166000908152600a60205260409020805460ff1916911515919091179055565b600060026001541415610c8e5760405162461bcd60e51b815260040161062590613d2f565b60026001556000610c9e84611bad565b83519091508114610cf15760405162461bcd60e51b815260206004820152601c60248201527f4261736545786368616e67653a20554e4d4154434845445f48415348000000006044820152606401610625565b60208301516001600160a01b0316610d4b5760405162461bcd60e51b815260206004820152601c60248201527f4261736545786368616e67653a20494e56414c49445f5349474e4552000000006044820152606401610625565b610d71610d5784612710565b84602001518560c001518660e00151876101000151611cea565b610d91818560000151866101a00151876101c00151886101e00151611cea565b610db4848285602001518660400151876060015188608001518960a00151611f2f565b60018055949350505050565b6000826001600160a01b0316826001600160a01b03161415610de457506001610ec0565b813b15610ebc5760408051600481526024810182526020810180516001600160e01b0316638da5cb5b60e01b179052905160009182916001600160a01b03861691610e2e91613c2d565b600060405180830381855afa9150503d8060008114610e69576040519150601f19603f3d011682016040523d82523d6000602084013e610e6e565b606091505b50915091508115610eb957600081806020019051810190610e8f9190613814565b9050856001600160a01b0316816001600160a01b03161415610eb75760019350505050610ec0565b505b50505b5060005b92915050565b6001600160a01b0390811660009081526007602090815260408083205460089092529091205491169160ff90911690565b600081815260026020818152604080842081516102008101835281546001600160a01b03908116825260018301548116948201949094529381015491840191909152600381015460608401526004810154821660808401526005810154821660a08401526006810154821660c0840152600781015460e0840152600881015491821661010084015260ff600160a01b83048116610120850152600160a81b909204909116610140830152600981018054849384938493849361016084019190610fbf90614077565b80601f0160208091040260200160405190810160405280929190818152602001828054610feb90614077565b80156110385780601f1061100d57610100808354040283529160200191611038565b820191906000526020600020905b81548152906001019060200180831161101b57829003601f168201915b5050509183525050600a8201546020820152600b82015460ff166040820152600c8201546060820152600d909101546080909101526101808101516101a08201516101c08301516101e0909301519199909850919650945092505050565b6006546001600160a01b031633146110c05760405162461bcd60e51b815260040161062590613d9f565b6110ca600061279e565b565b600081815260026020818152604080842081516102008101835281546001600160a01b03908116825260018301548116948201949094529381015491840191909152600381015460608401526004810154821660808401526005810154821660a08401526006810154821660c0840152600781015460e0840152600881015491821661010084015260ff600160a01b83048116610120850152600160a81b9092049091166101408301526009810180546101608401919061118c90614077565b80601f01602080910402602001604051908101604052809291908181526020018280546111b890614077565b80156112055780601f106111da57610100808354040283529160200191611205565b820191906000526020600020905b8154815290600101906020018083116111e857829003601f168201915b5050509183525050600a8201546020820152600b82015460ff166040820152600c8201546060820152600d9091015460809091015280519091506001600160a01b031633146112905760405162461bcd60e51b81526020600482015260176024820152762130b9b2a2bc31b430b733b29d102327a92124a22222a760491b6044820152606401610625565b61129981611bad565b82146112e75760405162461bcd60e51b815260206004820152601c60248201527f4261736545786368616e67653a20484153485f4e4f545f4d41544348000000006044820152606401610625565b60008281526003602052604090819020608083015160e08401516101608501518354600285015460058601549651632546b5a560e01b815295966001600160a01b0395861696632546b5a5966113499695941692918391839190600401613f5b565b60206040518083038186803b15801561136157600080fd5b505afa158015611375573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139991906139f2565b6113e55760405162461bcd60e51b815260206004820152601c60248201527f4261736545786368616e67653a2043414e5f4e4f545f43414e43454c000000006044820152606401610625565b600083815260046020526040808220805460ff191660011790555184917fe8d9861dbc9c663ed3accd261bbe2fe01e0d3d9e5f51fa38523b265c7757a93a91a2505050565b6001600160a01b0381166000908152600a602052604090205460ff165b919050565b6009546001600160a01b03811691600160a01b90910460ff1690565b60006002600154141561148d5760405162461bcd60e51b815260040161062590613d2f565b6002600181815560008881526020838152604080832081516102008101835281546001600160a01b039081168252958201548616938101939093529485015490820152600384015460608201526004840154831660808201526005840154831660a08201526006840154831660c0820152600784015460e0820152600884015492831661010082015260ff600160a01b84048116610120830152600160a81b9093049092166101408301526009830180549193916101608401919061155190614077565b80601f016020809104026020016040519081016040528092919081815260200182805461157d90614077565b80156115ca5780601f1061159f576101008083540402835291602001916115ca565b820191906000526020600020905b8154815290600101906020018083116115ad57829003601f168201915b5050509183525050600a8201546020820152600b82015460ff166040820152600c8201546060820152600d90910154608090910152905061160a81611bad565b87146116285760405162461bcd60e51b815260040161062590613dd4565b61098081883389898989611f2f565b600081815260026020818152604080842081516102008101835281546001600160a01b0390811682526001830154811694820194909452938101549184019190915260038101546060848101919091526004820154831660808501526005820154831660a08501526006820154831660c0850152600782015460e0850152600882015492831661010085015260ff600160a01b84048116610120860152600160a81b90930490921661014084015260098101805485948594859485948594859485948594859485949293859390929161016084019161171590614077565b80601f016020809104026020016040519081016040528092919081815260200182805461174190614077565b801561178e5780601f106117635761010080835404028352916020019161178e565b820191906000526020600020905b81548152906001019060200180831161177157829003601f168201915b50505050508152602001600a8201548152602001600b820160009054906101000a900460ff1660ff1660ff168152602001600c8201548152602001600d820154815250509050806000015181602001518260400151836060015184608001518560a001518660c001518760e001518861010001518961012001518a61014001518b61016001519c509c509c509c509c509c509c509c509c509c509c509c505091939597999b5091939597999b565b6000600260015414156118615760405162461bcd60e51b815260040161062590613d2f565b60026001819055506000604051806102000160405280336001600160a01b031681526020018e6001600160a01b031681526020018d81526020018c81526020018b6001600160a01b031681526020018a6001600160a01b03168152602001896001600160a01b03168152602001888152602001876001600160a01b031681526020018660008151811061190457634e487b7160e01b600052603260045260246000fd5b602002602001015160ff1681526020018660018151811061193557634e487b7160e01b600052603260045260246000fd5b602002602001015160ff168152602001858152602001848152602001600060ff1681526020016000801b81526020016000801b815250905061197681611bad565b600081815260026020818152604092839020855181546001600160a01b03199081166001600160a01b039283161783558784015160018401805483169184169190911790559487015193820193909355606086015160038201556080860151600482018054861691851691909117905560a0860151600582018054861691851691909117905560c08601516006820180549095169084161790935560e08501516007840155610100850151600884018054610120880151610140890151939095166001600160a81b031990911617600160a01b60ff958616021760ff60a81b1916600160a81b94909216939093021790915561016084015180519395508493611a859260098501920190613522565b50610180820151600a8201556101a0820151600b8201805460ff191660ff9092169190911790556101c0820151600c8201556101e090910151600d9091015560405182907fa35cf631f3c5fbb3057404c6a65199c474f4fa15dc4e12c0b3f13b4483a4fec090611af6908490613e1a565b60405180910390a250600180559b9a5050505050505050505050565b6006546001600160a01b03163314611b3c5760405162461bcd60e51b815260040161062590613d9f565b6001600160a01b038116611ba15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610625565b611baa8161279e565b50565b6000808261016001515160fa611bc39190613fd9565b905060008167ffffffffffffffff811115611bee57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611c18576020820181803683370190505b5084519091506020820190611c2e9082906127f0565b9050611c3e8186602001516127f0565b604086810151825260608701516020830152608087015191019150611c649082906127f0565b9050611c74818660a001516127f0565b9050611c84818660c001516127f0565b60e086015181529050602081019050611ca2818661010001516127f0565b9050611cb38186610120015161280a565b9050611cc48186610140015161280a565b9050611cd581866101600151612817565b61018086015181529050506020012092915050565b60007f5db69c81c664d97f8caf39ff79c2a9f0503ecac2939aeef98292e01de7e687a160405161190160f01b6020820152602281019190915260428101879052606201604051602081830303815290604052805190602001209050611d4f853b151590565b15611e6957604080516020810185905280820184905260f886901b6001600160f81b0319166060820152815160418183030181526061820192839052630b135d3f60e11b9092526001600160a01b03871691631626ba7e91611db5918591606501613d03565b60206040518083038186803b158015611dcd57600080fd5b505afa158015611de1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e059190613a7b565b6001600160e01b031916631626ba7e60e01b14611e645760405162461bcd60e51b815260206004820152601a60248201527f4261736545786368616e67653a20554e415554484f52495a45440000000000006044820152606401610625565b611f27565b60408051600081526020810180835283905260ff86169181019190915260608101849052608081018390526001600160a01b0386169060019060a0016020604051602081039080840390855afa158015611ec7573d6000803e3d6000fd5b505050602060405103516001600160a01b031614611f275760405162461bcd60e51b815260206004820152601a60248201527f4261736545786368616e67653a20554e415554484f52495a45440000000000006044820152606401610625565b505050505050565b6000808511611f805760405162461bcd60e51b815260206004820152601c60248201527f4261736545786368616e67653a20494e56414c49445f414d4f554e54000000006044820152606401610625565b6060880151600088815260056020526040902054611f9e908761285a565b1115611fe55760405162461bcd60e51b815260206004820152601660248201527510985cd9515e18da185b99d94e8814d3d31117d3d55560521b6044820152606401610625565b611fef888861286d565b600060036000898152602001908152602001600020905088608001516001600160a01b031663651199518a60e001518b61016001518a898660000160009054906101000a90046001600160a01b0316876002015488600501546040518863ffffffff1660e01b815260040161206a9796959493929190613f5b565b60206040518083038186803b15801561208257600080fd5b505afa158015612096573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ba91906139f2565b1561223c576000888152600560205260409020546120d8908761285a565b60008981526005602052604090205560c08901516001600160a01b0381166120fe575088515b60006040518061012001604052808c602001516001600160a01b031681526020018c60a001516001600160a01b031681526020018a6001600160a01b03168152602001836001600160a01b03168152602001898961215c9190614011565b81526020018c61010001516001600160a01b031681526020018c610120015160ff168152602001866001600160a01b031681526020018c610140015160ff1681525090506121a981612a97565b6121c55760405162461bcd60e51b815260040161062590613d59565b6001600160a01b0386166121d7578895505b6121f08b602001518c60000151888e604001518c612e9c565b897f0642c67a22e8657a7126bb3b9fb3f01965503642f884e4c6a1efd8ed24f46c0d8a8a8a8a8a604051612228959493929190613cd1565b60405180910390a2600193505050506123d0565b88608001516001600160a01b0316635f11a72b8a60e001518b61016001518a898660000160009054906101000a90046001600160a01b0316876002015488600501546040518863ffffffff1660e01b81526004016122a09796959493929190613f5b565b60206040518083038186803b1580156122b857600080fd5b505afa1580156122cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f091906139f2565b156123905780546001600160a01b038089166001600160a01b031992831617835560018301889055600283018790556003830180548783169084161790556004830180549186169190921617905543600582015560405188907f4055f76fe1f351fec66b9ba790ddbdc29eb45c038163a6b1327277441a8c65f19061237e908a908a908a908a908a90613cd1565b60405180910390a260009150506123d0565b60405162461bcd60e51b81526020600482015260156024820152744261736545786368616e67653a204641494c55524560581b6044820152606401610625565b979650505050505050565b6123e5828261286d565b600081815260036020818152604092839020835160c08101855281546001600160a01b0390811680835260018401549483019490945260028301548287018190529483015481166060830152600480840154821660808085019190915260059094015460a084018190529389015160e08a01516101608b01519851636511995160e01b81529498919093169663651199519661248e969495929490939192849284929101613f5b565b60206040518083038186803b1580156124a657600080fd5b505afa1580156124ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124de91906139f2565b6125225760405162461bcd60e51b81526020600482015260156024820152744261736545786368616e67653a204641494c55524560581b6044820152606401610625565b60c08301516001600160a01b038116612539575082515b6000838152600460209081526040808320805460ff19166001179055805161012081018252878301516001600160a01b03908116825260a08901518116828501528651811682840152851660608201529185015190850151608083019161259f91614011565b81526020018661010001516001600160a01b0316815260200186610120015160ff16815260200184608001516001600160a01b0316815260200186610140015160ff1681525090506125f081612a97565b61260c5760405162461bcd60e51b815260040161062590613d59565b6020808401516000868152600590925260409091205461262b9161285a565b60008581526005602052604090205560608301516001600160a01b038116612651575082515b61266e866020015187600001518389604001518860200151612e9c565b600085815260036020818152604080842080546001600160a01b031990811682556001820186905560028201869055938101805485169055600481018054909416909355600590920192909255855191860151868201516080880151925189947f0642c67a22e8657a7126bb3b9fb3f01965503642f884e4c6a1efd8ed24f46c0d946127009491939192889190613cd1565b60405180910390a2505050505050565b80516020808301516040808501516060860151608087015160a08801519351600097612781979096959101958652606094851b6bffffffffffffffffffffffff19908116602088015260348701949094526054860192909252831b8216607485015290911b166088820152609c0190565b604051602081830303815290604052805190602001209050919050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60601b6bffffffffffffffffffffffff1916815260140190565b6000818353505060010190565b80516000901561285357815180602001830160208401855b6001838310141561284a57815181526020918201910161282f565b50505092909201915b5090919050565b60006128668284613fd9565b9392505050565b60008181526004602052604090205460ff16156128cc5760405162461bcd60e51b815260206004820152601760248201527f4261736545786368616e67653a2043414e43454c4c45440000000000000000006044820152606401610625565b81516001600160a01b03166129235760405162461bcd60e51b815260206004820152601b60248201527f4261736545786368616e67653a20494e56414c49445f4d414b455200000000006044820152606401610625565b60208201516001600160a01b031661297d5760405162461bcd60e51b815260206004820152601960248201527f4261736545786368616e67653a20494e56414c49445f4e4654000000000000006044820152606401610625565b60008260600151116129d15760405162461bcd60e51b815260206004820152601c60248201527f4261736545786368616e67653a20494e56414c49445f414d4f554e54000000006044820152606401610625565b60808201516001600160a01b0316612a2b5760405162461bcd60e51b815260206004820152601e60248201527f4261736545786368616e67653a20494e56414c49445f535452415445475900006044820152606401610625565b612a38826080015161142a565b612a935760405162461bcd60e51b815260206004820152602660248201527f4261736545786368616e67653a2053545241544547595f4e4f545f5748495445604482015265131254d5115160d21b6064820152608401610625565b5050565b60208101516000906001600160a01b0316612c6f5734826080015114612abf57506000611447565b6080820151600080612acf61144c565b90925090506001600160a01b03821615612b265760006103e88260ff168760800151612afb9190614011565b612b059190613ff1565b90508015612b2457612b1783826130bd565b612b218185614030565b93505b505b60a08501516001600160a01b031615612b845760006103e88660c0015160ff168760800151612b559190614011565b612b5f9190613ff1565b90508015612b8257612b758660a00151826130bd565b612b7f8185614030565b93505b505b600080612b948760000151610ec6565b90925090506001600160a01b03821615612bf45760ff81811614612bf45760006103e88260ff168960800151612bca9190614011565b612bd49190613ff1565b90508015612bf257612be68187614030565b9550612bf283826130bd565b505b60e08701516001600160a01b031615612c535760006103e888610100015160ff168960800151612c249190614011565b612c2e9190613ff1565b90508015612c5157612c448860e00151826130bd565b612c4e8187614030565b95505b505b612c618760600151866130bd565b600195505050505050611447565b612c87826020015183604001513085608001516131db565b612c9357506000611447565b6080820151600080612ca361144c565b90925090506001600160a01b03821615612d095760006103e88260ff168760800151612ccf9190614011565b612cd99190613ff1565b90508015612d07576020860151612cfa906001600160a01b031684836132ad565b612d048185614030565b93505b505b60a08501516001600160a01b031615612d7f5760006103e88660c0015160ff168760800151612d389190614011565b612d429190613ff1565b90508015612d7d57612d708660a001518288602001516001600160a01b03166132ad9092919063ffffffff16565b612d7a8185614030565b93505b505b600080612d8f8760000151610ec6565b90925090506001600160a01b03821615612dff5760ff81811614612dff5760006103e88260ff168960800151612dc59190614011565b612dcf9190613ff1565b90508015612dfd57612de18187614030565b6020890151909650612dfd906001600160a01b031684836132ad565b505b60e08701516001600160a01b031615612e765760006103e888610100015160ff168960800151612e2f9190614011565b612e399190613ff1565b90508015612e7457612e678860e00151828a602001516001600160a01b03166132ad9092919063ffffffff16565b612e718187614030565b95505b505b612c6187606001518689602001516001600160a01b03166132ad9092919063ffffffff16565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526001600160a01b038616906301ffc9a79060240160206040518083038186803b158015612ee257600080fd5b505afa158015612ef6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1a91906139f2565b15612f8f57604051632142170760e11b81526001600160a01b0385811660048301528481166024830152604482018490528616906342842e0e906064015b600060405180830381600087803b158015612f7257600080fd5b505af1158015612f86573d6000803e3d6000fd5b505050506130b6565b6040516301ffc9a760e01b8152636cdb3d1360e11b60048201526001600160a01b038616906301ffc9a79060240160206040518083038186803b158015612fd557600080fd5b505afa158015612fe9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061300d91906139f2565b1561306457604051637921219560e11b81526001600160a01b0385811660048301528481166024830152604482018490526064820183905260a06084830152600060a483015286169063f242432a9060c401612f58565b60405162461bcd60e51b815260206004820152602160248201527f4e65774e465445786368616e67653a20756e737570706f7274656420746f6b656044820152603760f91b6064820152608401610625565b5050505050565b8047101561310d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610625565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461315a576040519150601f19603f3d011682016040523d82523d6000602084013e61315f565b606091505b50509050806131d65760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610625565b505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b179052915160009283928392918916916132419190613c2d565b6000604051808303816000865af19150503d806000811461327e576040519150601f19603f3d011682016040523d82523d6000602084013e613283565b606091505b50915091508180156123d05750805115806123d05750808060200190518101906123d091906139f2565b604080516001600160a01b03848116602483015260448083018590528351808403909101815260649092018352602080830180516001600160e01b031663a9059cbb60e01b17905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908401526131d69286929160009161333d9185169084906133ba565b8051909150156131d6578080602001905181019061335b91906139f2565b6131d65760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610625565b60606133c984846000856133d1565b949350505050565b6060824710156134325760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610625565b843b6134805760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610625565b600080866001600160a01b0316858760405161349c9190613c2d565b60006040518083038185875af1925050503d80600081146134d9576040519150601f19603f3d011682016040523d82523d6000602084013e6134de565b606091505b50915091506123d0828286606083156134f8575081612866565b8251156135085782518084602001fd5b8160405162461bcd60e51b81526004016106259190613d1c565b82805461352e90614077565b90600052602060002090601f0160209004810192826135505760008555613596565b82601f1061356957805160ff1916838001178555613596565b82800160010185558215613596579182015b8281111561359657825182559160200191906001019061357b565b506135a29291506135a6565b5090565b5b808211156135a257600081556001016135a7565b8035611447816140de565b600082601f8301126135d6578081fd5b8135602067ffffffffffffffff8211156135f2576135f26140c8565b8160051b613601828201613fa8565b83815282810190868401838801850189101561361b578687fd5b8693505b8584101561364457613630816137e7565b83526001939093019291840191840161361f565b50979650505050505050565b600082601f830112613660578081fd5b813567ffffffffffffffff81111561367a5761367a6140c8565b61368d601f8201601f1916602001613fa8565b8181528460208386010111156136a1578283fd5b816020850160208301379081016020019190915292915050565b60006102008083850312156136ce578182fd5b6136d781613fa8565b9150506136e3826135bb565b81526136f1602083016135bb565b60208201526040820135604082015260608201356060820152613716608083016135bb565b608082015261372760a083016135bb565b60a082015261373860c083016135bb565b60c082015260e082013560e08201526101006137558184016135bb565b908201526101206137678382016137e7565b908201526101406137798382016137e7565b908201526101608281013567ffffffffffffffff81111561379957600080fd5b6137a585828601613650565b8284015250506101808083013581830152506101a06137c58184016137e7565b908201526101c082810135908201526101e09182013591810191909152919050565b803560ff8116811461144757600080fd5b600060208284031215613809578081fd5b8135612866816140de565b600060208284031215613825578081fd5b8151612866816140de565b60008060408385031215613842578081fd5b823561384d816140de565b9150602083013561385d816140de565b809150509250929050565b60008060006060848603121561387c578081fd5b8335613887816140de565b92506020840135613897816140de565b91506138a5604085016137e7565b90509250925092565b600080604083850312156138c0578182fd5b82356138cb816140de565b9150602083013561385d816140f3565b60008060008060008060008060008060006101608c8e0312156138fc578687fd5b6139058c6135bb565b9a5060208c0135995060408c0135985061392160608d016135bb565b975061392f60808d016135bb565b965061393d60a08d016135bb565b955060c08c0135945061395260e08d016135bb565b935067ffffffffffffffff806101008e0135111561396e578384fd5b61397f8e6101008f01358f016135c6565b9350806101208e01351115613992578283fd5b506139a48d6101208e01358e01613650565b91506101408c013590509295989b509295989b9093969950565b600080604083850312156139d0578182fd5b82356139db816140de565b91506139e9602084016137e7565b90509250929050565b600060208284031215613a03578081fd5b8151612866816140f3565b600060208284031215613a1f578081fd5b5035919050565b600080600080600060a08688031215613a3d578283fd5b8535945060208601359350604086013592506060860135613a5d816140de565b91506080860135613a6d816140de565b809150509295509295909350565b600060208284031215613a8c578081fd5b81516001600160e01b031981168114612866578182fd5b600060208284031215613ab4578081fd5b813567ffffffffffffffff811115613aca578182fd5b6133c9848285016136bb565b600080828403610140811215613aea578283fd5b833567ffffffffffffffff811115613b00578384fd5b613b0c868287016136bb565b93505061012080601f1983011215613b22578283fd5b613b2b81613fa8565b915060208501358252613b40604086016135bb565b60208301526060850135604083015260808501356060830152613b6560a086016135bb565b6080830152613b7660c086016135bb565b60a0830152613b8760e086016137e7565b60c08301526101008581013560e0840152940135938101939093525092909150565b600080600080600060a08688031215613bc0578283fd5b853567ffffffffffffffff811115613bd6578384fd5b613be2888289016136bb565b95505060208601359350604086013592506060860135613a5d816140de565b60008151808452613c19816020860160208601614047565b601f01601f19169290920160200192915050565b60008251613c3f818460208701614047565b9190910192915050565b6001600160a01b038d811682528c81166020830152604082018c9052606082018b9052898116608083015288811660a083015287811660c083015260e08201879052851661010082015260ff84811661012083015283166101408201526000610180610160830152613cbf610180830184613c01565b9e9d5050505050505050505050505050565b6001600160a01b0395861681526020810194909452604084019290925283166060830152909116608082015260a00190565b6000838252604060208301526133c96040830184613c01565b6000602082526128666020830184613c01565b60208082526010908201526f14d213d6554e8814915153951490539560821b604082015260600190565b60208082526026908201527f4261736545786368616e67653a204641494c45445f544f5f5452414e534645526040820152655f46554e445360d01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526026908201527f4261736545786368616e67653a20554e4d4154434845445f41534b5f4f5244456040820152650a4be9082a6960d31b606082015260800190565b600060208252613e366020830184516001600160a01b03169052565b60208301516001600160a01b03811660408401525060408301516060830152606083015160808301526080830151613e7960a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e083015161010083810191909152830151610120613ecd818501836001600160a01b03169052565b8401519050610140613ee38482018360ff169052565b8401519050610160613ef98482018360ff169052565b808501519150506102006101808181860152613f19610220860184613c01565b908601516101a0868101919091528601519092506101c0613f3e8187018360ff169052565b8601516101e0868101919091529095015193019290925250919050565b600088825260e06020830152613f7460e0830189613c01565b6001600160a01b03978816604084015260608301969096525092909416608083015260a082015260c0019190915292915050565b604051601f8201601f1916810167ffffffffffffffff81118282101715613fd157613fd16140c8565b604052919050565b60008219821115613fec57613fec6140b2565b500190565b60008261400c57634e487b7160e01b81526012600452602481fd5b500490565b600081600019048311821515161561402b5761402b6140b2565b500290565b600082821015614042576140426140b2565b500390565b60005b8381101561406257818101518382015260200161404a565b83811115614071576000848401525b50505050565b600181811c9082168061408b57607f821691505b602082108114156140ac57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114611baa57600080fd5b8015158114611baa57600080fdfea2646970667358221220b178a3eacdb448f0ff528a5af51ea8c24b546497efb04a376b219717a71f452f64736f6c63430008030033