编译器
0.8.17+commit.8df45f5f
文件 1 的 46:AffiliateManager.sol
pragma solidity 0.8.17;
import {OwnableTwoSteps} from "@looksrare/contracts-libs/contracts/OwnableTwoSteps.sol";
import {IAffiliateManager} from "./interfaces/IAffiliateManager.sol";
import {ONE_HUNDRED_PERCENT_IN_BP} from "./constants/NumericConstants.sol";
contract AffiliateManager is IAffiliateManager, OwnableTwoSteps {
bool public isAffiliateProgramActive;
address public affiliateController;
mapping(address => uint256) public affiliateRates;
constructor(address _owner) OwnableTwoSteps(_owner) {}
function updateAffiliateRate(address affiliate, uint256 bp) external {
if (msg.sender != affiliateController) {
revert NotAffiliateController();
}
if (bp > ONE_HUNDRED_PERCENT_IN_BP) {
revert PercentageTooHigh();
}
affiliateRates[affiliate] = bp;
emit NewAffiliateRate(affiliate, bp);
}
function updateAffiliateController(address newAffiliateController) external onlyOwner {
affiliateController = newAffiliateController;
emit NewAffiliateController(newAffiliateController);
}
function updateAffiliateProgramStatus(bool isActive) external onlyOwner {
isAffiliateProgramActive = isActive;
emit NewAffiliateProgramStatus(isActive);
}
}
文件 2 的 46:AssemblyConstants.sol
pragma solidity 0.8.17;
uint256 constant OrderInvalid_error_selector = 0x2e0c0f71;
uint256 constant OrderInvalid_error_length = 0x04;
uint256 constant CurrencyInvalid_error_selector = 0x4f795487;
uint256 constant CurrencyInvalid_error_length = 0x04;
uint256 constant OutsideOfTimeRange_error_selector = 0x7476320f;
uint256 constant OutsideOfTimeRange_error_length = 0x04;
uint256 constant NoSelectorForStrategy_error_selector = 0xab984846;
uint256 constant NoSelectorForStrategy_error_length = 0x04;
uint256 constant Error_selector_offset = 0x1c;
uint256 constant OneWord = 0x20;
文件 3 的 46:BatchOrderTypehashRegistry.sol
pragma solidity 0.8.17;
import {MerkleProofTooLarge} from "./errors/SharedErrors.sol";
contract BatchOrderTypehashRegistry {
function hashBatchOrder(bytes32 root, uint256 proofLength) public pure returns (bytes32 batchOrderHash) {
batchOrderHash = keccak256(abi.encode(_getBatchOrderTypehash(proofLength), root));
}
function _getBatchOrderTypehash(uint256 height) internal pure returns (bytes32 typehash) {
if (height == 1) {
typehash = hex"9661287f7a4aa4867db46a2453ee15bebac4e8fc25667a58718da658f15de643";
} else if (height == 2) {
typehash = hex"a54ab330ea9e1dfccee2b86f3666989e7fbd479704416c757c8de8e820142a08";
} else if (height == 3) {
typehash = hex"93390f5d45ede9dea305f16aec86b2472af4f823851637f1b7019ad0775cea49";
} else if (height == 4) {
typehash = hex"9dda2c8358da895e43d574bb15954ce5727b22e923a2d8f28261f297bce42f0b";
} else if (height == 5) {
typehash = hex"92dc717124e161262f9d10c7079e7d54dc51271893fba54aa4a0f270fecdcc98";
} else if (height == 6) {
typehash = hex"ce02aee5a7a35d40d974463c4c6e5534954fb07a7e7bc966fee268a15337bfd8";
} else if (height == 7) {
typehash = hex"f7a65efd167a18f7091b2bb929d687dd94503cf0a43620487055ed7d6b727559";
} else if (height == 8) {
typehash = hex"def24acacad1318b664520f7c10e8bc6d1e7f6f6f7c8b031e70624ceb42266a6";
} else if (height == 9) {
typehash = hex"4cb4080dc4e7bae88b4dc4307ad5117fa4f26195998a1b5f40368809d7f4c7f2";
} else if (height == 10) {
typehash = hex"f8b1f864164d8d6e0b45f1399bd711223117a4ab0b057a9c2d7779e86a7c88db";
} else {
revert MerkleProofTooLarge(height);
}
}
}
文件 4 的 46:CollectionType.sol
pragma solidity 0.8.17;
enum CollectionType {
ERC721,
ERC1155
}
文件 5 的 46:CurrencyManager.sol
pragma solidity 0.8.17;
import {ICurrencyManager} from "./interfaces/ICurrencyManager.sol";
import {AffiliateManager} from "./AffiliateManager.sol";
contract CurrencyManager is ICurrencyManager, AffiliateManager {
mapping(address => bool) public isCurrencyAllowed;
constructor(address _owner) AffiliateManager(_owner) {}
function updateCurrencyStatus(address currency, bool isAllowed) external onlyOwner {
isCurrencyAllowed[currency] = isAllowed;
emit CurrencyStatusUpdated(currency, isAllowed);
}
}
文件 6 的 46:ExecutionManager.sol
pragma solidity 0.8.17;
import {OrderStructs} from "./libraries/OrderStructs.sol";
import {IExecutionManager} from "./interfaces/IExecutionManager.sol";
import {ICreatorFeeManager} from "./interfaces/ICreatorFeeManager.sol";
import {InheritedStrategy} from "./InheritedStrategy.sol";
import {NonceManager} from "./NonceManager.sol";
import {StrategyManager} from "./StrategyManager.sol";
import {NoSelectorForStrategy_error_selector, NoSelectorForStrategy_error_length, OutsideOfTimeRange_error_selector, OutsideOfTimeRange_error_length, Error_selector_offset} from "./constants/AssemblyConstants.sol";
import {ONE_HUNDRED_PERCENT_IN_BP} from "./constants/NumericConstants.sol";
import {QuoteType} from "./enums/QuoteType.sol";
contract ExecutionManager is InheritedStrategy, NonceManager, StrategyManager, IExecutionManager {
address public protocolFeeRecipient;
uint16 public maxCreatorFeeBp = 1_000;
ICreatorFeeManager public creatorFeeManager;
constructor(address _owner, address _protocolFeeRecipient) StrategyManager(_owner) {
_updateProtocolFeeRecipient(_protocolFeeRecipient);
}
function updateCreatorFeeManager(address newCreatorFeeManager) external onlyOwner {
creatorFeeManager = ICreatorFeeManager(newCreatorFeeManager);
emit NewCreatorFeeManager(newCreatorFeeManager);
}
function updateMaxCreatorFeeBp(uint16 newMaxCreatorFeeBp) external onlyOwner {
if (newMaxCreatorFeeBp > 2_500) {
revert CreatorFeeBpTooHigh();
}
maxCreatorFeeBp = newMaxCreatorFeeBp;
emit NewMaxCreatorFeeBp(newMaxCreatorFeeBp);
}
function updateProtocolFeeRecipient(address newProtocolFeeRecipient) external onlyOwner {
_updateProtocolFeeRecipient(newProtocolFeeRecipient);
}
function _executeStrategyForTakerOrder(
OrderStructs.Taker calldata takerOrder,
OrderStructs.Maker calldata makerOrder,
address sender
)
internal
returns (
uint256[] memory itemIds,
uint256[] memory amounts,
address[2] memory recipients,
uint256[3] memory feeAmounts,
bool isNonceInvalidated
)
{
uint256 price;
_verifyOrderTimestampValidity(makerOrder.startTime, makerOrder.endTime);
if (makerOrder.strategyId == 0) {
_verifyItemIdsAndAmountsEqualLengthsAndValidAmounts(makerOrder.amounts, makerOrder.itemIds);
(price, itemIds, amounts) = (makerOrder.price, makerOrder.itemIds, makerOrder.amounts);
isNonceInvalidated = true;
} else {
if (strategyInfo[makerOrder.strategyId].isActive) {
QuoteType quoteType = makerOrder.quoteType;
bool isMakerBid = strategyInfo[makerOrder.strategyId].isMakerBid;
assembly {
if eq(quoteType, isMakerBid) {
mstore(0x00, NoSelectorForStrategy_error_selector)
revert(Error_selector_offset, NoSelectorForStrategy_error_length)
}
}
(bool status, bytes memory data) = strategyInfo[makerOrder.strategyId].implementation.call(
abi.encodeWithSelector(strategyInfo[makerOrder.strategyId].selector, takerOrder, makerOrder)
);
if (!status) {
assembly {
revert(add(data, 32), mload(data))
}
}
(price, itemIds, amounts, isNonceInvalidated) = abi.decode(data, (uint256, uint256[], uint256[], bool));
} else {
revert StrategyNotAvailable(makerOrder.strategyId);
}
}
(recipients[1], feeAmounts[1]) = _getCreatorRecipientAndCalculateFeeAmount(
makerOrder.collection,
price,
itemIds
);
if (makerOrder.quoteType == QuoteType.Bid) {
_setTheRestOfFeeAmountsAndRecipients(
makerOrder.strategyId,
price,
takerOrder.recipient == address(0) ? sender : takerOrder.recipient,
feeAmounts,
recipients
);
} else {
_setTheRestOfFeeAmountsAndRecipients(
makerOrder.strategyId,
price,
makerOrder.signer,
feeAmounts,
recipients
);
}
}
function _updateProtocolFeeRecipient(address newProtocolFeeRecipient) private {
if (newProtocolFeeRecipient == address(0)) {
revert NewProtocolFeeRecipientCannotBeNullAddress();
}
protocolFeeRecipient = newProtocolFeeRecipient;
emit NewProtocolFeeRecipient(newProtocolFeeRecipient);
}
function _calculateProtocolFeeAmount(
uint256 price,
uint256 strategyId,
uint256 creatorFeeAmount,
uint256 minTotalFeeAmount
) private view returns (uint256 protocolFeeAmount) {
protocolFeeAmount = (price * strategyInfo[strategyId].standardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP;
if (protocolFeeAmount + creatorFeeAmount < minTotalFeeAmount) {
protocolFeeAmount = minTotalFeeAmount - creatorFeeAmount;
}
}
function _getCreatorRecipientAndCalculateFeeAmount(
address collection,
uint256 price,
uint256[] memory itemIds
) private view returns (address creator, uint256 creatorFeeAmount) {
if (address(creatorFeeManager) != address(0)) {
(creator, creatorFeeAmount) = creatorFeeManager.viewCreatorFeeInfo(collection, price, itemIds);
if (creator == address(0)) {
creatorFeeAmount = 0;
} else if (creatorFeeAmount * ONE_HUNDRED_PERCENT_IN_BP > (price * uint256(maxCreatorFeeBp))) {
revert CreatorFeeBpTooHigh();
}
}
}
function _setTheRestOfFeeAmountsAndRecipients(
uint256 strategyId,
uint256 price,
address askRecipient,
uint256[3] memory feeAmounts,
address[2] memory recipients
) private view {
uint256 minTotalFeeAmount = (price * strategyInfo[strategyId].minTotalFeeBp) / ONE_HUNDRED_PERCENT_IN_BP;
if (feeAmounts[1] == 0) {
feeAmounts[2] = minTotalFeeAmount;
feeAmounts[0] = price - feeAmounts[2];
} else {
feeAmounts[2] = _calculateProtocolFeeAmount(price, strategyId, feeAmounts[1], minTotalFeeAmount);
feeAmounts[0] = price - feeAmounts[1] - feeAmounts[2];
}
recipients[0] = askRecipient;
}
function _verifyOrderTimestampValidity(uint256 startTime, uint256 endTime) private view {
assembly {
if or(gt(startTime, timestamp()), lt(endTime, timestamp())) {
mstore(0x00, OutsideOfTimeRange_error_selector)
revert(Error_selector_offset, OutsideOfTimeRange_error_length)
}
}
}
}
文件 7 的 46:GenericErrors.sol
pragma solidity ^0.8.17;
error NotAContract();
文件 8 的 46:IAffiliateManager.sol
pragma solidity 0.8.17;
interface IAffiliateManager {
event NewAffiliateController(address affiliateController);
event NewAffiliateProgramStatus(bool isActive);
event NewAffiliateRate(address affiliate, uint256 rate);
error NotAffiliateController();
error PercentageTooHigh();
}
文件 9 的 46:ICreatorFeeManager.sol
pragma solidity 0.8.17;
import {IRoyaltyFeeRegistry} from "./IRoyaltyFeeRegistry.sol";
interface ICreatorFeeManager {
error BundleEIP2981NotAllowed(address collection);
function royaltyFeeRegistry() external view returns (IRoyaltyFeeRegistry royaltyFeeRegistry);
function viewCreatorFeeInfo(
address collection,
uint256 price,
uint256[] memory itemIds
) external view returns (address creator, uint256 creatorFeeAmount);
}
文件 10 的 46:ICurrencyManager.sol
pragma solidity 0.8.17;
interface ICurrencyManager {
event CurrencyStatusUpdated(address currency, bool isAllowed);
}
文件 11 的 46:IERC1155.sol
pragma solidity ^0.8.17;
interface IERC1155 {
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}
文件 12 的 46:IERC1271.sol
pragma solidity ^0.8.17;
interface IERC1271 {
function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4 magicValue);
}
文件 13 的 46:IERC20.sol
pragma solidity ^0.8.17;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 14 的 46:IERC721.sol
pragma solidity ^0.8.17;
interface IERC721 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function setApprovalForAll(address operator, bool _approved) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
文件 15 的 46:IExecutionManager.sol
pragma solidity 0.8.17;
interface IExecutionManager {
event NewCreatorFeeManager(address creatorFeeManager);
event NewMaxCreatorFeeBp(uint256 maxCreatorFeeBp);
event NewProtocolFeeRecipient(address protocolFeeRecipient);
error CreatorFeeBpTooHigh();
error NewProtocolFeeRecipientCannotBeNullAddress();
error NoSelectorForStrategy();
error OutsideOfTimeRange();
error StrategyNotAvailable(uint256 strategyId);
}
文件 16 的 46:ILooksRareProtocol.sol
pragma solidity 0.8.17;
import {OrderStructs} from "../libraries/OrderStructs.sol";
interface ILooksRareProtocol {
struct NonceInvalidationParameters {
bytes32 orderHash;
uint256 orderNonce;
bool isNonceInvalidated;
}
event AffiliatePayment(address affiliate, address currency, uint256 affiliateFee);
event NewDomainSeparator();
event NewGasLimitETHTransfer(uint256 gasLimitETHTransfer);
event TakerAsk(
NonceInvalidationParameters nonceInvalidationParameters,
address askUser,
address bidUser,
uint256 strategyId,
address currency,
address collection,
uint256[] itemIds,
uint256[] amounts,
address[2] feeRecipients,
uint256[3] feeAmounts
);
event TakerBid(
NonceInvalidationParameters nonceInvalidationParameters,
address bidUser,
address bidRecipient,
uint256 strategyId,
address currency,
address collection,
uint256[] itemIds,
uint256[] amounts,
address[2] feeRecipients,
uint256[3] feeAmounts
);
error NewGasLimitETHTransferTooLow();
error SameDomainSeparator();
error ChainIdInvalid();
error NoncesInvalid();
function executeTakerAsk(
OrderStructs.Taker calldata takerAsk,
OrderStructs.Maker calldata makerBid,
bytes calldata makerSignature,
OrderStructs.MerkleTree calldata merkleTree,
address affiliate
) external;
function executeTakerBid(
OrderStructs.Taker calldata takerBid,
OrderStructs.Maker calldata makerAsk,
bytes calldata makerSignature,
OrderStructs.MerkleTree calldata merkleTree,
address affiliate
) external payable;
function executeMultipleTakerBids(
OrderStructs.Taker[] calldata takerBids,
OrderStructs.Maker[] calldata makerAsks,
bytes[] calldata makerSignatures,
OrderStructs.MerkleTree[] calldata merkleTrees,
address affiliate,
bool isAtomic
) external payable;
}
文件 17 的 46:INonceManager.sol
pragma solidity 0.8.17;
interface INonceManager {
struct UserBidAskNonces {
uint256 bidNonce;
uint256 askNonce;
}
event NewBidAskNonces(address user, uint256 bidNonce, uint256 askNonce);
event OrderNoncesCancelled(address user, uint256[] orderNonces);
event SubsetNoncesCancelled(address user, uint256[] subsetNonces);
}
文件 18 的 46:IOwnableTwoSteps.sol
pragma solidity ^0.8.17;
interface IOwnableTwoSteps {
enum Status {
NoOngoingTransfer,
TransferInProgress,
RenouncementInProgress
}
error NoOngoingTransferInProgress();
error NotOwner();
error RenouncementNotInProgress();
error TransferAlreadyInProgress();
error TransferNotInProgress();
error WrongPotentialOwner();
event CancelOwnershipTransfer();
event InitiateOwnershipRenouncement();
event InitiateOwnershipTransfer(address previousOwner, address potentialOwner);
event NewOwner(address newOwner);
}
文件 19 的 46:IReentrancyGuard.sol
pragma solidity ^0.8.17;
interface IReentrancyGuard {
error ReentrancyFail();
}
文件 20 的 46:IRoyaltyFeeRegistry.sol
pragma solidity 0.8.17;
interface IRoyaltyFeeRegistry {
function royaltyInfo(
address collection,
uint256 price
) external view returns (address receiver, uint256 royaltyFee);
}
文件 21 的 46:IStrategy.sol
pragma solidity 0.8.17;
import {OrderStructs} from "../libraries/OrderStructs.sol";
interface IStrategy {
function isMakerOrderValid(
OrderStructs.Maker calldata makerOrder,
bytes4 functionSelector
) external view returns (bool isValid, bytes4 errorSelector);
function isLooksRareV2Strategy() external pure returns (bool isStrategy);
}
文件 22 的 46:IStrategyManager.sol
pragma solidity 0.8.17;
interface IStrategyManager {
struct Strategy {
bool isActive;
uint16 standardProtocolFeeBp;
uint16 minTotalFeeBp;
uint16 maxProtocolFeeBp;
bytes4 selector;
bool isMakerBid;
address implementation;
}
event NewStrategy(
uint256 strategyId,
uint16 standardProtocolFeeBp,
uint16 minTotalFeeBp,
uint16 maxProtocolFeeBp,
bytes4 selector,
bool isMakerBid,
address implementation
);
event StrategyUpdated(uint256 strategyId, bool isActive, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp);
error NotV2Strategy();
error StrategyHasNoSelector();
error StrategyNotUsed();
error StrategyProtocolFeeTooHigh();
}
文件 23 的 46:ITransferManager.sol
pragma solidity 0.8.17;
import {OrderStructs} from "../libraries/OrderStructs.sol";
import {CollectionType} from "../enums/CollectionType.sol";
interface ITransferManager {
struct BatchTransferItem {
address collection;
CollectionType collectionType;
uint256[] itemIds;
uint256[] amounts;
}
event ApprovalsGranted(address user, address[] operators);
event ApprovalsRemoved(address user, address[] operators);
event OperatorAllowed(address operator);
event OperatorRemoved(address operator);
error OperatorAlreadyApprovedByUser();
error OperatorNotApprovedByUser();
error OperatorAlreadyAllowed();
error OperatorNotAllowed();
error TransferCallerInvalid();
}
文件 24 的 46:IWETH.sol
pragma solidity >=0.5.0;
interface IWETH {
function deposit() external payable;
function transfer(address dst, uint256 wad) external returns (bool);
function withdraw(uint256 wad) external;
}
文件 25 的 46:InheritedStrategy.sol
pragma solidity 0.8.17;
import {OrderStructs} from "./libraries/OrderStructs.sol";
import {OrderInvalid} from "./errors/SharedErrors.sol";
import {OrderInvalid_error_selector, OrderInvalid_error_length, Error_selector_offset, OneWord} from "./constants/AssemblyConstants.sol";
contract InheritedStrategy {
function _verifyItemIdsAndAmountsEqualLengthsAndValidAmounts(
uint256[] calldata amounts,
uint256[] calldata itemIds
) internal pure {
assembly {
let end
{
let amountsLength := amounts.length
let itemIdsLength := itemIds.length
if or(iszero(amountsLength), xor(amountsLength, itemIdsLength)) {
mstore(0x00, OrderInvalid_error_selector)
revert(Error_selector_offset, OrderInvalid_error_length)
}
end := shl(5, amountsLength)
}
let amountsOffset := amounts.offset
for {
} end {
} {
end := sub(end, OneWord)
let amount := calldataload(add(amountsOffset, end))
if iszero(amount) {
mstore(0x00, OrderInvalid_error_selector)
revert(Error_selector_offset, OrderInvalid_error_length)
}
}
}
}
}
文件 26 的 46:LooksRareProtocol.sol
pragma solidity 0.8.17;
import {SignatureCheckerCalldata} from "@looksrare/contracts-libs/contracts/SignatureCheckerCalldata.sol";
import {LowLevelETHReturnETHIfAnyExceptOneWei} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelETHReturnETHIfAnyExceptOneWei.sol";
import {LowLevelWETH} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelWETH.sol";
import {LowLevelERC20Transfer} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC20Transfer.sol";
import {MerkleProofCalldataWithNodes} from "./libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol";
import {OrderStructs} from "./libraries/OrderStructs.sol";
import {ILooksRareProtocol} from "./interfaces/ILooksRareProtocol.sol";
import {CallerInvalid, CurrencyInvalid, LengthsInvalid, MerkleProofInvalid, MerkleProofTooLarge, QuoteTypeInvalid} from "./errors/SharedErrors.sol";
import {TransferSelectorNFT} from "./TransferSelectorNFT.sol";
import {BatchOrderTypehashRegistry} from "./BatchOrderTypehashRegistry.sol";
import {MAX_CALLDATA_PROOF_LENGTH, ONE_HUNDRED_PERCENT_IN_BP} from "./constants/NumericConstants.sol";
import {QuoteType} from "./enums/QuoteType.sol";
contract LooksRareProtocol is
ILooksRareProtocol,
TransferSelectorNFT,
LowLevelETHReturnETHIfAnyExceptOneWei,
LowLevelWETH,
LowLevelERC20Transfer,
BatchOrderTypehashRegistry
{
using OrderStructs for OrderStructs.Maker;
address public immutable WETH;
uint256 public chainId;
bytes32 public domainSeparator;
uint256 private _gasLimitETHTransfer = 2_300;
constructor(
address _owner,
address _protocolFeeRecipient,
address _transferManager,
address _weth
) TransferSelectorNFT(_owner, _protocolFeeRecipient, _transferManager) {
_updateDomainSeparator();
WETH = _weth;
}
function executeTakerAsk(
OrderStructs.Taker calldata takerAsk,
OrderStructs.Maker calldata makerBid,
bytes calldata makerSignature,
OrderStructs.MerkleTree calldata merkleTree,
address affiliate
) external nonReentrant {
address currency = makerBid.currency;
if (!isCurrencyAllowed[currency] || currency == address(0)) {
revert CurrencyInvalid();
}
address signer = makerBid.signer;
bytes32 orderHash = makerBid.hash();
_verifyMerkleProofOrOrderHash(merkleTree, orderHash, makerSignature, signer);
uint256 totalProtocolFeeAmount = _executeTakerAsk(takerAsk, makerBid, orderHash);
_payProtocolFeeAndAffiliateFee(currency, signer, affiliate, totalProtocolFeeAmount);
}
function executeTakerBid(
OrderStructs.Taker calldata takerBid,
OrderStructs.Maker calldata makerAsk,
bytes calldata makerSignature,
OrderStructs.MerkleTree calldata merkleTree,
address affiliate
) external payable nonReentrant {
address currency = makerAsk.currency;
if (!isCurrencyAllowed[currency]) {
revert CurrencyInvalid();
}
bytes32 orderHash = makerAsk.hash();
_verifyMerkleProofOrOrderHash(merkleTree, orderHash, makerSignature, makerAsk.signer);
uint256 totalProtocolFeeAmount = _executeTakerBid(takerBid, makerAsk, msg.sender, orderHash);
_payProtocolFeeAndAffiliateFee(currency, msg.sender, affiliate, totalProtocolFeeAmount);
_returnETHIfAnyWithOneWeiLeft();
}
function executeMultipleTakerBids(
OrderStructs.Taker[] calldata takerBids,
OrderStructs.Maker[] calldata makerAsks,
bytes[] calldata makerSignatures,
OrderStructs.MerkleTree[] calldata merkleTrees,
address affiliate,
bool isAtomic
) external payable nonReentrant {
uint256 length = takerBids.length;
if (
length == 0 ||
(makerAsks.length ^ length) | (makerSignatures.length ^ length) | (merkleTrees.length ^ length) != 0
) {
revert LengthsInvalid();
}
address currency = makerAsks[0].currency;
if (!isCurrencyAllowed[currency]) {
revert CurrencyInvalid();
}
{
uint256 totalProtocolFeeAmount;
if (isAtomic) {
for (uint256 i; i < length; ) {
OrderStructs.Maker calldata makerAsk = makerAsks[i];
if (i != 0) {
if (makerAsk.currency != currency) {
revert CurrencyInvalid();
}
}
OrderStructs.Taker calldata takerBid = takerBids[i];
bytes32 orderHash = makerAsk.hash();
{
_verifyMerkleProofOrOrderHash(merkleTrees[i], orderHash, makerSignatures[i], makerAsk.signer);
totalProtocolFeeAmount += _executeTakerBid(takerBid, makerAsk, msg.sender, orderHash);
unchecked {
++i;
}
}
}
} else {
for (uint256 i; i < length; ) {
OrderStructs.Maker calldata makerAsk = makerAsks[i];
if (i != 0) {
if (makerAsk.currency != currency) {
revert CurrencyInvalid();
}
}
OrderStructs.Taker calldata takerBid = takerBids[i];
bytes32 orderHash = makerAsk.hash();
{
_verifyMerkleProofOrOrderHash(merkleTrees[i], orderHash, makerSignatures[i], makerAsk.signer);
try this.restrictedExecuteTakerBid(takerBid, makerAsk, msg.sender, orderHash) returns (
uint256 protocolFeeAmount
) {
totalProtocolFeeAmount += protocolFeeAmount;
} catch {}
unchecked {
++i;
}
}
}
}
_payProtocolFeeAndAffiliateFee(currency, msg.sender, affiliate, totalProtocolFeeAmount);
}
_returnETHIfAnyWithOneWeiLeft();
}
function restrictedExecuteTakerBid(
OrderStructs.Taker calldata takerBid,
OrderStructs.Maker calldata makerAsk,
address sender,
bytes32 orderHash
) external returns (uint256 protocolFeeAmount) {
if (msg.sender != address(this)) {
revert CallerInvalid();
}
protocolFeeAmount = _executeTakerBid(takerBid, makerAsk, sender, orderHash);
}
function updateDomainSeparator() external onlyOwner {
if (block.chainid != chainId) {
_updateDomainSeparator();
emit NewDomainSeparator();
} else {
revert SameDomainSeparator();
}
}
function updateETHGasLimitForTransfer(uint256 newGasLimitETHTransfer) external onlyOwner {
if (newGasLimitETHTransfer < 2_300) {
revert NewGasLimitETHTransferTooLow();
}
_gasLimitETHTransfer = newGasLimitETHTransfer;
emit NewGasLimitETHTransfer(newGasLimitETHTransfer);
}
function _executeTakerAsk(
OrderStructs.Taker calldata takerAsk,
OrderStructs.Maker calldata makerBid,
bytes32 orderHash
) internal returns (uint256) {
if (makerBid.quoteType != QuoteType.Bid) {
revert QuoteTypeInvalid();
}
address signer = makerBid.signer;
{
bytes32 userOrderNonceStatus = userOrderNonce[signer][makerBid.orderNonce];
if (
userBidAskNonces[signer].bidNonce != makerBid.globalNonce ||
userSubsetNonce[signer][makerBid.subsetNonce] ||
(userOrderNonceStatus != bytes32(0) && userOrderNonceStatus != orderHash)
) {
revert NoncesInvalid();
}
}
(
uint256[] memory itemIds,
uint256[] memory amounts,
address[2] memory recipients,
uint256[3] memory feeAmounts,
bool isNonceInvalidated
) = _executeStrategyForTakerOrder(takerAsk, makerBid, msg.sender);
_updateUserOrderNonce(isNonceInvalidated, signer, makerBid.orderNonce, orderHash);
_transferNFT(makerBid.collection, makerBid.collectionType, msg.sender, signer, itemIds, amounts);
_transferToAskRecipientAndCreatorIfAny(recipients, feeAmounts, makerBid.currency, signer);
emit TakerAsk(
NonceInvalidationParameters({
orderHash: orderHash,
orderNonce: makerBid.orderNonce,
isNonceInvalidated: isNonceInvalidated
}),
msg.sender,
signer,
makerBid.strategyId,
makerBid.currency,
makerBid.collection,
itemIds,
amounts,
recipients,
feeAmounts
);
return feeAmounts[2];
}
function _executeTakerBid(
OrderStructs.Taker calldata takerBid,
OrderStructs.Maker calldata makerAsk,
address sender,
bytes32 orderHash
) internal returns (uint256) {
if (makerAsk.quoteType != QuoteType.Ask) {
revert QuoteTypeInvalid();
}
address signer = makerAsk.signer;
{
bytes32 userOrderNonceStatus = userOrderNonce[signer][makerAsk.orderNonce];
if (
userBidAskNonces[signer].askNonce != makerAsk.globalNonce ||
userSubsetNonce[signer][makerAsk.subsetNonce] ||
(userOrderNonceStatus != bytes32(0) && userOrderNonceStatus != orderHash)
) {
revert NoncesInvalid();
}
}
(
uint256[] memory itemIds,
uint256[] memory amounts,
address[2] memory recipients,
uint256[3] memory feeAmounts,
bool isNonceInvalidated
) = _executeStrategyForTakerOrder(takerBid, makerAsk, msg.sender);
_updateUserOrderNonce(isNonceInvalidated, signer, makerAsk.orderNonce, orderHash);
_transferToAskRecipientAndCreatorIfAny(recipients, feeAmounts, makerAsk.currency, sender);
_transferNFT(
makerAsk.collection,
makerAsk.collectionType,
signer,
takerBid.recipient == address(0) ? sender : takerBid.recipient,
itemIds,
amounts
);
emit TakerBid(
NonceInvalidationParameters({
orderHash: orderHash,
orderNonce: makerAsk.orderNonce,
isNonceInvalidated: isNonceInvalidated
}),
sender,
takerBid.recipient == address(0) ? sender : takerBid.recipient,
makerAsk.strategyId,
makerAsk.currency,
makerAsk.collection,
itemIds,
amounts,
recipients,
feeAmounts
);
return feeAmounts[2];
}
function _payProtocolFeeAndAffiliateFee(
address currency,
address bidUser,
address affiliate,
uint256 totalProtocolFeeAmount
) internal {
if (totalProtocolFeeAmount != 0) {
if (affiliate != address(0)) {
if (isAffiliateProgramActive) {
uint256 totalAffiliateFeeAmount = (totalProtocolFeeAmount * affiliateRates[affiliate]) /
ONE_HUNDRED_PERCENT_IN_BP;
if (totalAffiliateFeeAmount != 0) {
totalProtocolFeeAmount -= totalAffiliateFeeAmount;
if (bidUser != affiliate) {
_transferFungibleTokens(currency, bidUser, affiliate, totalAffiliateFeeAmount);
}
emit AffiliatePayment(affiliate, currency, totalAffiliateFeeAmount);
}
}
}
_transferFungibleTokens(currency, bidUser, protocolFeeRecipient, totalProtocolFeeAmount);
}
}
function _transferFungibleTokens(address currency, address sender, address recipient, uint256 amount) internal {
if (currency == address(0)) {
_transferETHAndWrapIfFailWithGasLimit(WETH, recipient, amount, _gasLimitETHTransfer);
} else {
_executeERC20TransferFrom(currency, sender, recipient, amount);
}
}
function _transferToAskRecipientAndCreatorIfAny(
address[2] memory recipients,
uint256[3] memory feeAmounts,
address currency,
address bidUser
) private {
uint256 sellerProceed = feeAmounts[0];
if (sellerProceed != 0) {
_transferFungibleTokens(currency, bidUser, recipients[0], sellerProceed);
}
uint256 creatorFeeAmount = feeAmounts[1];
if (creatorFeeAmount != 0) {
_transferFungibleTokens(currency, bidUser, recipients[1], creatorFeeAmount);
}
}
function _updateDomainSeparator() private {
domainSeparator = keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256("LooksRareProtocol"),
keccak256(bytes("2")),
block.chainid,
address(this)
)
);
chainId = block.chainid;
}
function _updateUserOrderNonce(
bool isNonceInvalidated,
address signer,
uint256 orderNonce,
bytes32 orderHash
) private {
userOrderNonce[signer][orderNonce] = (isNonceInvalidated ? MAGIC_VALUE_ORDER_NONCE_EXECUTED : orderHash);
}
function _computeDigestAndVerify(bytes32 computedHash, bytes calldata makerSignature, address signer) private view {
if (chainId == block.chainid) {
SignatureCheckerCalldata.verify(
keccak256(abi.encodePacked("\x19\x01", domainSeparator, computedHash)),
signer,
makerSignature
);
} else {
revert ChainIdInvalid();
}
}
function _verifyMerkleProofOrOrderHash(
OrderStructs.MerkleTree calldata merkleTree,
bytes32 orderHash,
bytes calldata signature,
address signer
) private view {
uint256 proofLength = merkleTree.proof.length;
if (proofLength != 0) {
if (proofLength > MAX_CALLDATA_PROOF_LENGTH) {
revert MerkleProofTooLarge(proofLength);
}
if (!MerkleProofCalldataWithNodes.verifyCalldata(merkleTree.proof, merkleTree.root, orderHash)) {
revert MerkleProofInvalid();
}
orderHash = hashBatchOrder(merkleTree.root, proofLength);
}
_computeDigestAndVerify(orderHash, signature, signer);
}
}
文件 27 的 46:LowLevelERC1155Transfer.sol
pragma solidity ^0.8.17;
import {IERC1155} from "../interfaces/generic/IERC1155.sol";
import {ERC1155SafeTransferFromFail, ERC1155SafeBatchTransferFromFail} from "../errors/LowLevelErrors.sol";
import {NotAContract} from "../errors/GenericErrors.sol";
contract LowLevelERC1155Transfer {
function _executeERC1155SafeTransferFrom(
address collection,
address from,
address to,
uint256 tokenId,
uint256 amount
) internal {
if (collection.code.length == 0) {
revert NotAContract();
}
(bool status, ) = collection.call(abi.encodeCall(IERC1155.safeTransferFrom, (from, to, tokenId, amount, "")));
if (!status) {
revert ERC1155SafeTransferFromFail();
}
}
function _executeERC1155SafeBatchTransferFrom(
address collection,
address from,
address to,
uint256[] calldata tokenIds,
uint256[] calldata amounts
) internal {
if (collection.code.length == 0) {
revert NotAContract();
}
(bool status, ) = collection.call(
abi.encodeCall(IERC1155.safeBatchTransferFrom, (from, to, tokenIds, amounts, ""))
);
if (!status) {
revert ERC1155SafeBatchTransferFromFail();
}
}
}
文件 28 的 46:LowLevelERC20Transfer.sol
pragma solidity ^0.8.17;
import {IERC20} from "../interfaces/generic/IERC20.sol";
import {ERC20TransferFail, ERC20TransferFromFail} from "../errors/LowLevelErrors.sol";
import {NotAContract} from "../errors/GenericErrors.sol";
contract LowLevelERC20Transfer {
function _executeERC20TransferFrom(address currency, address from, address to, uint256 amount) internal {
if (currency.code.length == 0) {
revert NotAContract();
}
(bool status, bytes memory data) = currency.call(abi.encodeCall(IERC20.transferFrom, (from, to, amount)));
if (!status) {
revert ERC20TransferFromFail();
}
if (data.length > 0) {
if (!abi.decode(data, (bool))) {
revert ERC20TransferFromFail();
}
}
}
function _executeERC20DirectTransfer(address currency, address to, uint256 amount) internal {
if (currency.code.length == 0) {
revert NotAContract();
}
(bool status, bytes memory data) = currency.call(abi.encodeCall(IERC20.transfer, (to, amount)));
if (!status) {
revert ERC20TransferFail();
}
if (data.length > 0) {
if (!abi.decode(data, (bool))) {
revert ERC20TransferFail();
}
}
}
}
文件 29 的 46:LowLevelERC721Transfer.sol
pragma solidity ^0.8.17;
import {IERC721} from "../interfaces/generic/IERC721.sol";
import {ERC721TransferFromFail} from "../errors/LowLevelErrors.sol";
import {NotAContract} from "../errors/GenericErrors.sol";
contract LowLevelERC721Transfer {
function _executeERC721TransferFrom(address collection, address from, address to, uint256 tokenId) internal {
if (collection.code.length == 0) {
revert NotAContract();
}
(bool status, ) = collection.call(abi.encodeCall(IERC721.transferFrom, (from, to, tokenId)));
if (!status) {
revert ERC721TransferFromFail();
}
}
}
文件 30 的 46:LowLevelETHReturnETHIfAnyExceptOneWei.sol
pragma solidity ^0.8.17;
import {ETHTransferFail_error_selector, ETHTransferFail_error_length, Error_selector_offset} from "../constants/AssemblyConstants.sol";
contract LowLevelETHReturnETHIfAnyExceptOneWei {
function _returnETHIfAnyWithOneWeiLeft() internal {
assembly {
let selfBalance := selfbalance()
if gt(selfBalance, 1) {
let status := call(gas(), caller(), sub(selfBalance, 1), 0, 0, 0, 0)
if iszero(status) {
mstore(0x00, ETHTransferFail_error_selector)
revert(Error_selector_offset, ETHTransferFail_error_length)
}
}
}
}
}
文件 31 的 46:LowLevelErrors.sol
pragma solidity ^0.8.17;
error ETHTransferFail();
error ERC20ApprovalFail();
error ERC20TransferFail();
error ERC20TransferFromFail();
error ERC721TransferFromFail();
error ERC1155SafeTransferFromFail();
error ERC1155SafeBatchTransferFromFail();
文件 32 的 46:LowLevelWETH.sol
pragma solidity ^0.8.17;
import {IWETH} from "../interfaces/generic/IWETH.sol";
contract LowLevelWETH {
function _transferETHAndWrapIfFailWithGasLimit(
address _WETH,
address _to,
uint256 _amount,
uint256 _gasLimit
) internal {
bool status;
assembly {
status := call(_gasLimit, _to, _amount, 0, 0, 0, 0)
}
if (!status) {
IWETH(_WETH).deposit{value: _amount}();
IWETH(_WETH).transfer(_to, _amount);
}
}
}
文件 33 的 46:MerkleProofCalldataWithNodes.sol
pragma solidity 0.8.17;
import {OrderStructs} from "../../libraries/OrderStructs.sol";
library MerkleProofCalldataWithNodes {
function verifyCalldata(
OrderStructs.MerkleTreeNode[] calldata proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
return processProofCalldata(proof, leaf) == root;
}
function processProofCalldata(
OrderStructs.MerkleTreeNode[] calldata proof,
bytes32 leaf
) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
uint256 length = proof.length;
for (uint256 i = 0; i < length; ) {
if (proof[i].position == OrderStructs.MerkleTreeNodePosition.Left) {
computedHash = _efficientHash(proof[i].value, computedHash);
} else {
computedHash = _efficientHash(computedHash, proof[i].value);
}
unchecked {
++i;
}
}
return computedHash;
}
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}
文件 34 的 46:NonceManager.sol
pragma solidity 0.8.17;
import {INonceManager} from "./interfaces/INonceManager.sol";
import {LengthsInvalid} from "./errors/SharedErrors.sol";
contract NonceManager is INonceManager {
bytes32 public constant MAGIC_VALUE_ORDER_NONCE_EXECUTED = keccak256("ORDER_NONCE_EXECUTED");
mapping(address => UserBidAskNonces) public userBidAskNonces;
mapping(address => mapping(uint256 => bytes32)) public userOrderNonce;
mapping(address => mapping(uint256 => bool)) public userSubsetNonce;
function cancelOrderNonces(uint256[] calldata orderNonces) external {
uint256 length = orderNonces.length;
if (length == 0) {
revert LengthsInvalid();
}
for (uint256 i; i < length; ) {
userOrderNonce[msg.sender][orderNonces[i]] = MAGIC_VALUE_ORDER_NONCE_EXECUTED;
unchecked {
++i;
}
}
emit OrderNoncesCancelled(msg.sender, orderNonces);
}
function cancelSubsetNonces(uint256[] calldata subsetNonces) external {
uint256 length = subsetNonces.length;
if (length == 0) {
revert LengthsInvalid();
}
for (uint256 i; i < length; ) {
userSubsetNonce[msg.sender][subsetNonces[i]] = true;
unchecked {
++i;
}
}
emit SubsetNoncesCancelled(msg.sender, subsetNonces);
}
function incrementBidAskNonces(bool bid, bool ask) external {
uint256 quasiRandomNumber = uint256(blockhash(block.number - 1) >> 128);
uint256 newBidNonce = userBidAskNonces[msg.sender].bidNonce;
uint256 newAskNonce = userBidAskNonces[msg.sender].askNonce;
if (bid) {
newBidNonce += quasiRandomNumber;
userBidAskNonces[msg.sender].bidNonce = newBidNonce;
}
if (ask) {
newAskNonce += quasiRandomNumber;
userBidAskNonces[msg.sender].askNonce = newAskNonce;
}
emit NewBidAskNonces(msg.sender, newBidNonce, newAskNonce);
}
}
文件 35 的 46:NumericConstants.sol
pragma solidity 0.8.17;
uint256 constant ONE_HUNDRED_PERCENT_IN_BP = 10_000;
uint256 constant MAX_CALLDATA_PROOF_LENGTH = 10;
文件 36 的 46:OrderStructs.sol
pragma solidity 0.8.17;
import {CollectionType} from "../enums/CollectionType.sol";
import {QuoteType} from "../enums/QuoteType.sol";
library OrderStructs {
struct Maker {
QuoteType quoteType;
uint256 globalNonce;
uint256 subsetNonce;
uint256 orderNonce;
uint256 strategyId;
CollectionType collectionType;
address collection;
address currency;
address signer;
uint256 startTime;
uint256 endTime;
uint256 price;
uint256[] itemIds;
uint256[] amounts;
bytes additionalParameters;
}
struct Taker {
address recipient;
bytes additionalParameters;
}
enum MerkleTreeNodePosition { Left, Right }
struct MerkleTreeNode {
bytes32 value;
MerkleTreeNodePosition position;
}
struct MerkleTree {
bytes32 root;
MerkleTreeNode[] proof;
}
bytes32 internal constant _MAKER_TYPEHASH =
keccak256(
"Maker("
"uint8 quoteType,"
"uint256 globalNonce,"
"uint256 subsetNonce,"
"uint256 orderNonce,"
"uint256 strategyId,"
"uint8 collectionType,"
"address collection,"
"address currency,"
"address signer,"
"uint256 startTime,"
"uint256 endTime,"
"uint256 price,"
"uint256[] itemIds,"
"uint256[] amounts,"
"bytes additionalParameters"
")"
);
function hash(Maker memory maker) internal pure returns (bytes32) {
return
keccak256(
bytes.concat(
abi.encode(
_MAKER_TYPEHASH,
maker.quoteType,
maker.globalNonce,
maker.subsetNonce,
maker.orderNonce,
maker.strategyId,
maker.collectionType,
maker.collection,
maker.currency
),
abi.encode(
maker.signer,
maker.startTime,
maker.endTime,
maker.price,
keccak256(abi.encodePacked(maker.itemIds)),
keccak256(abi.encodePacked(maker.amounts)),
keccak256(maker.additionalParameters)
)
)
);
}
}
文件 37 的 46:OwnableTwoSteps.sol
pragma solidity ^0.8.17;
import {IOwnableTwoSteps} from "./interfaces/IOwnableTwoSteps.sol";
abstract contract OwnableTwoSteps is IOwnableTwoSteps {
address public owner;
address public potentialOwner;
Status public ownershipStatus;
modifier onlyOwner() {
_onlyOwner();
_;
}
constructor(address _owner) {
owner = _owner;
emit NewOwner(_owner);
}
function cancelOwnershipTransfer() external onlyOwner {
Status _ownershipStatus = ownershipStatus;
if (_ownershipStatus == Status.NoOngoingTransfer) {
revert NoOngoingTransferInProgress();
}
if (_ownershipStatus == Status.TransferInProgress) {
delete potentialOwner;
}
delete ownershipStatus;
emit CancelOwnershipTransfer();
}
function confirmOwnershipRenouncement() external onlyOwner {
if (ownershipStatus != Status.RenouncementInProgress) {
revert RenouncementNotInProgress();
}
delete owner;
delete ownershipStatus;
emit NewOwner(address(0));
}
function confirmOwnershipTransfer() external {
if (ownershipStatus != Status.TransferInProgress) {
revert TransferNotInProgress();
}
if (msg.sender != potentialOwner) {
revert WrongPotentialOwner();
}
owner = msg.sender;
delete ownershipStatus;
delete potentialOwner;
emit NewOwner(msg.sender);
}
function initiateOwnershipTransfer(address newPotentialOwner) external onlyOwner {
if (ownershipStatus != Status.NoOngoingTransfer) {
revert TransferAlreadyInProgress();
}
ownershipStatus = Status.TransferInProgress;
potentialOwner = newPotentialOwner;
emit InitiateOwnershipTransfer(msg.sender, newPotentialOwner);
}
function initiateOwnershipRenouncement() external onlyOwner {
if (ownershipStatus != Status.NoOngoingTransfer) {
revert TransferAlreadyInProgress();
}
ownershipStatus = Status.RenouncementInProgress;
emit InitiateOwnershipRenouncement();
}
function _onlyOwner() private view {
if (msg.sender != owner) revert NotOwner();
}
}
文件 38 的 46:PackableReentrancyGuard.sol
pragma solidity ^0.8.17;
import {IReentrancyGuard} from "./interfaces/IReentrancyGuard.sol";
abstract contract PackableReentrancyGuard is IReentrancyGuard {
uint8 private _status;
modifier nonReentrant() {
if (_status == 2) {
revert ReentrancyFail();
}
_status = 2;
_;
_status = 1;
}
constructor() {
_status = 1;
}
}
文件 39 的 46:QuoteType.sol
pragma solidity 0.8.17;
enum QuoteType {
Bid,
Ask
}
文件 40 的 46:SharedErrors.sol
pragma solidity 0.8.17;
error AmountInvalid();
error AskTooHigh();
error BidTooLow();
error CallerInvalid();
error CurrencyInvalid();
error FunctionSelectorInvalid();
error LengthsInvalid();
error MerkleProofInvalid();
error MerkleProofTooLarge(uint256 length);
error OrderInvalid();
error QuoteTypeInvalid();
文件 41 的 46:SignatureCheckerCalldata.sol
pragma solidity ^0.8.17;
import {IERC1271} from "./interfaces/generic/IERC1271.sol";
import {ERC1271_MAGIC_VALUE} from "./constants/StandardConstants.sol";
import {SignatureParameterSInvalid, SignatureParameterVInvalid, SignatureERC1271Invalid, SignatureEOAInvalid, NullSignerAddress, SignatureLengthInvalid} from "./errors/SignatureCheckerErrors.sol";
library SignatureCheckerCalldata {
function verify(bytes32 hash, address signer, bytes calldata signature) internal view {
if (signer.code.length == 0) {
if (_recoverEOASigner(hash, signature) == signer) return;
revert SignatureEOAInvalid();
} else {
if (IERC1271(signer).isValidSignature(hash, signature) == ERC1271_MAGIC_VALUE) return;
revert SignatureERC1271Invalid();
}
}
function splitSignature(bytes calldata signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {
uint256 length = signature.length;
if (length == 65) {
assembly {
r := calldataload(signature.offset)
s := calldataload(add(signature.offset, 0x20))
v := byte(0, calldataload(add(signature.offset, 0x40)))
}
} else if (length == 64) {
assembly {
r := calldataload(signature.offset)
let vs := calldataload(add(signature.offset, 0x20))
s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
v := add(shr(255, vs), 27)
}
} else {
revert SignatureLengthInvalid(length);
}
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
revert SignatureParameterSInvalid();
}
if (v != 27 && v != 28) {
revert SignatureParameterVInvalid(v);
}
}
function _recoverEOASigner(bytes32 hash, bytes calldata signature) private pure returns (address signer) {
(bytes32 r, bytes32 s, uint8 v) = splitSignature(signature);
signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
revert NullSignerAddress();
}
}
}
文件 42 的 46:SignatureCheckerErrors.sol
pragma solidity ^0.8.17;
error NullSignerAddress();
error SignatureEOAInvalid();
error SignatureERC1271Invalid();
error SignatureLengthInvalid(uint256 length);
error SignatureParameterSInvalid();
error SignatureParameterVInvalid(uint8 v);
文件 43 的 46:StandardConstants.sol
pragma solidity ^0.8.17;
bytes4 constant ERC1271_MAGIC_VALUE = 0x1626ba7e;
文件 44 的 46:StrategyManager.sol
pragma solidity 0.8.17;
import {CurrencyManager} from "./CurrencyManager.sol";
import {IStrategy} from "./interfaces/IStrategy.sol";
import {IStrategyManager} from "./interfaces/IStrategyManager.sol";
contract StrategyManager is IStrategyManager, CurrencyManager {
uint256 private _countStrategies = 1;
mapping(uint256 => Strategy) public strategyInfo;
constructor(address _owner) CurrencyManager(_owner) {
strategyInfo[0] = Strategy({
isActive: true,
standardProtocolFeeBp: 50,
minTotalFeeBp: 50,
maxProtocolFeeBp: 200,
selector: bytes4(0),
isMakerBid: false,
implementation: address(0)
});
emit NewStrategy(0, 50, 50, 200, bytes4(0), false, address(0));
}
function addStrategy(
uint16 standardProtocolFeeBp,
uint16 minTotalFeeBp,
uint16 maxProtocolFeeBp,
bytes4 selector,
bool isMakerBid,
address implementation
) external onlyOwner {
if (minTotalFeeBp > maxProtocolFeeBp || standardProtocolFeeBp > minTotalFeeBp || maxProtocolFeeBp > 500) {
revert StrategyProtocolFeeTooHigh();
}
if (selector == bytes4(0)) {
revert StrategyHasNoSelector();
}
if (!IStrategy(implementation).isLooksRareV2Strategy()) {
revert NotV2Strategy();
}
strategyInfo[_countStrategies] = Strategy({
isActive: true,
standardProtocolFeeBp: standardProtocolFeeBp,
minTotalFeeBp: minTotalFeeBp,
maxProtocolFeeBp: maxProtocolFeeBp,
selector: selector,
isMakerBid: isMakerBid,
implementation: implementation
});
emit NewStrategy(
_countStrategies++,
standardProtocolFeeBp,
minTotalFeeBp,
maxProtocolFeeBp,
selector,
isMakerBid,
implementation
);
}
function updateStrategy(
uint256 strategyId,
bool isActive,
uint16 newStandardProtocolFee,
uint16 newMinTotalFee
) external onlyOwner {
if (strategyId >= _countStrategies) {
revert StrategyNotUsed();
}
if (newMinTotalFee > strategyInfo[strategyId].maxProtocolFeeBp || newStandardProtocolFee > newMinTotalFee) {
revert StrategyProtocolFeeTooHigh();
}
strategyInfo[strategyId].isActive = isActive;
strategyInfo[strategyId].standardProtocolFeeBp = newStandardProtocolFee;
strategyInfo[strategyId].minTotalFeeBp = newMinTotalFee;
emit StrategyUpdated(strategyId, isActive, newStandardProtocolFee, newMinTotalFee);
}
}
文件 45 的 46:TransferManager.sol
pragma solidity 0.8.17;
import {OwnableTwoSteps} from "@looksrare/contracts-libs/contracts/OwnableTwoSteps.sol";
import {LowLevelERC721Transfer} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC721Transfer.sol";
import {LowLevelERC1155Transfer} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC1155Transfer.sol";
import {ITransferManager} from "./interfaces/ITransferManager.sol";
import {AmountInvalid, LengthsInvalid} from "./errors/SharedErrors.sol";
import {OrderStructs} from "./libraries/OrderStructs.sol";
import {CollectionType} from "./enums/CollectionType.sol";
contract TransferManager is ITransferManager, LowLevelERC721Transfer, LowLevelERC1155Transfer, OwnableTwoSteps {
mapping(address => mapping(address => bool)) public hasUserApprovedOperator;
mapping(address => bool) public isOperatorAllowed;
constructor(address _owner) OwnableTwoSteps(_owner) {}
function transferItemsERC721(
address collection,
address from,
address to,
uint256[] calldata itemIds,
uint256[] calldata amounts
) external {
uint256 length = itemIds.length;
if (length == 0) {
revert LengthsInvalid();
}
_isOperatorValidForTransfer(from, msg.sender);
for (uint256 i; i < length; ) {
if (amounts[i] != 1) {
revert AmountInvalid();
}
_executeERC721TransferFrom(collection, from, to, itemIds[i]);
unchecked {
++i;
}
}
}
function transferItemsERC1155(
address collection,
address from,
address to,
uint256[] calldata itemIds,
uint256[] calldata amounts
) external {
uint256 length = itemIds.length;
if (length == 0 || amounts.length != length) {
revert LengthsInvalid();
}
_isOperatorValidForTransfer(from, msg.sender);
if (length == 1) {
if (amounts[0] == 0) {
revert AmountInvalid();
}
_executeERC1155SafeTransferFrom(collection, from, to, itemIds[0], amounts[0]);
} else {
for (uint256 i; i < length; ) {
if (amounts[i] == 0) {
revert AmountInvalid();
}
unchecked {
++i;
}
}
_executeERC1155SafeBatchTransferFrom(collection, from, to, itemIds, amounts);
}
}
function transferBatchItemsAcrossCollections(
BatchTransferItem[] calldata items,
address from,
address to
) external {
uint256 itemsLength = items.length;
if (itemsLength == 0) {
revert LengthsInvalid();
}
if (from != msg.sender) {
_isOperatorValidForTransfer(from, msg.sender);
}
for (uint256 i; i < itemsLength; ) {
uint256[] calldata itemIds = items[i].itemIds;
uint256 itemIdsLengthForSingleCollection = itemIds.length;
uint256[] calldata amounts = items[i].amounts;
if (itemIdsLengthForSingleCollection == 0 || amounts.length != itemIdsLengthForSingleCollection) {
revert LengthsInvalid();
}
CollectionType collectionType = items[i].collectionType;
if (collectionType == CollectionType.ERC721) {
for (uint256 j; j < itemIdsLengthForSingleCollection; ) {
if (amounts[j] != 1) {
revert AmountInvalid();
}
_executeERC721TransferFrom(items[i].collection, from, to, itemIds[j]);
unchecked {
++j;
}
}
} else if (collectionType == CollectionType.ERC1155) {
for (uint256 j; j < itemIdsLengthForSingleCollection; ) {
if (amounts[j] == 0) {
revert AmountInvalid();
}
unchecked {
++j;
}
}
_executeERC1155SafeBatchTransferFrom(items[i].collection, from, to, itemIds, amounts);
}
unchecked {
++i;
}
}
}
function grantApprovals(address[] calldata operators) external {
uint256 length = operators.length;
if (length == 0) {
revert LengthsInvalid();
}
for (uint256 i; i < length; ) {
address operator = operators[i];
if (!isOperatorAllowed[operator]) {
revert OperatorNotAllowed();
}
if (hasUserApprovedOperator[msg.sender][operator]) {
revert OperatorAlreadyApprovedByUser();
}
hasUserApprovedOperator[msg.sender][operator] = true;
unchecked {
++i;
}
}
emit ApprovalsGranted(msg.sender, operators);
}
function revokeApprovals(address[] calldata operators) external {
uint256 length = operators.length;
if (length == 0) {
revert LengthsInvalid();
}
for (uint256 i; i < length; ) {
address operator = operators[i];
if (!hasUserApprovedOperator[msg.sender][operator]) {
revert OperatorNotApprovedByUser();
}
delete hasUserApprovedOperator[msg.sender][operator];
unchecked {
++i;
}
}
emit ApprovalsRemoved(msg.sender, operators);
}
function allowOperator(address operator) external onlyOwner {
if (isOperatorAllowed[operator]) {
revert OperatorAlreadyAllowed();
}
isOperatorAllowed[operator] = true;
emit OperatorAllowed(operator);
}
function removeOperator(address operator) external onlyOwner {
if (!isOperatorAllowed[operator]) {
revert OperatorNotAllowed();
}
delete isOperatorAllowed[operator];
emit OperatorRemoved(operator);
}
function _isOperatorValidForTransfer(address user, address operator) private view {
if (isOperatorAllowed[operator] && hasUserApprovedOperator[user][operator]) {
return;
}
revert TransferCallerInvalid();
}
}
文件 46 的 46:TransferSelectorNFT.sol
pragma solidity 0.8.17;
import {PackableReentrancyGuard} from "@looksrare/contracts-libs/contracts/PackableReentrancyGuard.sol";
import {ExecutionManager} from "./ExecutionManager.sol";
import {TransferManager} from "./TransferManager.sol";
import {OrderStructs} from "./libraries/OrderStructs.sol";
import {CollectionType} from "./enums/CollectionType.sol";
contract TransferSelectorNFT is ExecutionManager, PackableReentrancyGuard {
TransferManager public immutable transferManager;
constructor(
address _owner,
address _protocolFeeRecipient,
address _transferManager
) ExecutionManager(_owner, _protocolFeeRecipient) {
transferManager = TransferManager(_transferManager);
}
function _transferNFT(
address collection,
CollectionType collectionType,
address sender,
address recipient,
uint256[] memory itemIds,
uint256[] memory amounts
) internal {
if (collectionType == CollectionType.ERC721) {
transferManager.transferItemsERC721(collection, sender, recipient, itemIds, amounts);
} else if (collectionType == CollectionType.ERC1155) {
transferManager.transferItemsERC1155(collection, sender, recipient, itemIds, amounts);
}
}
}
{
"compilationTarget": {
"contracts/LooksRareProtocol.sol": "LooksRareProtocol"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 888888
},
"remappings": [
":@chainlink/=node_modules/@chainlink/",
":@ensdomains/=node_modules/@ensdomains/",
":@eth-optimism/=node_modules/@eth-optimism/",
":@looksrare/=node_modules/@looksrare/",
":@openzeppelin/=node_modules/@openzeppelin/",
":ds-test/=lib/forge-std/lib/ds-test/src/",
":eth-gas-reporter/=node_modules/eth-gas-reporter/",
":forge-std/=lib/forge-std/src/",
":hardhat/=node_modules/hardhat/",
":murky/=lib/murky/src/",
":openzeppelin-contracts/=lib/murky/lib/openzeppelin-contracts/",
":solmate/=node_modules/solmate/"
]
}
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_protocolFeeRecipient","type":"address"},{"internalType":"address","name":"_transferManager","type":"address"},{"internalType":"address","name":"_weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerInvalid","type":"error"},{"inputs":[],"name":"ChainIdInvalid","type":"error"},{"inputs":[],"name":"CreatorFeeBpTooHigh","type":"error"},{"inputs":[],"name":"CurrencyInvalid","type":"error"},{"inputs":[],"name":"ERC20TransferFromFail","type":"error"},{"inputs":[],"name":"LengthsInvalid","type":"error"},{"inputs":[],"name":"MerkleProofInvalid","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"MerkleProofTooLarge","type":"error"},{"inputs":[],"name":"NewGasLimitETHTransferTooLow","type":"error"},{"inputs":[],"name":"NewProtocolFeeRecipientCannotBeNullAddress","type":"error"},{"inputs":[],"name":"NoOngoingTransferInProgress","type":"error"},{"inputs":[],"name":"NoSelectorForStrategy","type":"error"},{"inputs":[],"name":"NoncesInvalid","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"NotAffiliateController","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"NotV2Strategy","type":"error"},{"inputs":[],"name":"NullSignerAddress","type":"error"},{"inputs":[],"name":"OutsideOfTimeRange","type":"error"},{"inputs":[],"name":"PercentageTooHigh","type":"error"},{"inputs":[],"name":"QuoteTypeInvalid","type":"error"},{"inputs":[],"name":"ReentrancyFail","type":"error"},{"inputs":[],"name":"RenouncementNotInProgress","type":"error"},{"inputs":[],"name":"SameDomainSeparator","type":"error"},{"inputs":[],"name":"SignatureEOAInvalid","type":"error"},{"inputs":[],"name":"SignatureERC1271Invalid","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"SignatureLengthInvalid","type":"error"},{"inputs":[],"name":"SignatureParameterSInvalid","type":"error"},{"inputs":[{"internalType":"uint8","name":"v","type":"uint8"}],"name":"SignatureParameterVInvalid","type":"error"},{"inputs":[],"name":"StrategyHasNoSelector","type":"error"},{"inputs":[{"internalType":"uint256","name":"strategyId","type":"uint256"}],"name":"StrategyNotAvailable","type":"error"},{"inputs":[],"name":"StrategyNotUsed","type":"error"},{"inputs":[],"name":"StrategyProtocolFeeTooHigh","type":"error"},{"inputs":[],"name":"TransferAlreadyInProgress","type":"error"},{"inputs":[],"name":"TransferNotInProgress","type":"error"},{"inputs":[],"name":"WrongPotentialOwner","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"affiliate","type":"address"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"uint256","name":"affiliateFee","type":"uint256"}],"name":"AffiliatePayment","type":"event"},{"anonymous":false,"inputs":[],"name":"CancelOwnershipTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"bool","name":"isAllowed","type":"bool"}],"name":"CurrencyStatusUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"InitiateOwnershipRenouncement","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":false,"internalType":"address","name":"potentialOwner","type":"address"}],"name":"InitiateOwnershipTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"affiliateController","type":"address"}],"name":"NewAffiliateController","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isActive","type":"bool"}],"name":"NewAffiliateProgramStatus","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"affiliate","type":"address"},{"indexed":false,"internalType":"uint256","name":"rate","type":"uint256"}],"name":"NewAffiliateRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"bidNonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"askNonce","type":"uint256"}],"name":"NewBidAskNonces","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"creatorFeeManager","type":"address"}],"name":"NewCreatorFeeManager","type":"event"},{"anonymous":false,"inputs":[],"name":"NewDomainSeparator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"gasLimitETHTransfer","type":"uint256"}],"name":"NewGasLimitETHTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxCreatorFeeBp","type":"uint256"}],"name":"NewMaxCreatorFeeBp","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"protocolFeeRecipient","type":"address"}],"name":"NewProtocolFeeRecipient","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"strategyId","type":"uint256"},{"indexed":false,"internalType":"uint16","name":"standardProtocolFeeBp","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"minTotalFeeBp","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"maxProtocolFeeBp","type":"uint16"},{"indexed":false,"internalType":"bytes4","name":"selector","type":"bytes4"},{"indexed":false,"internalType":"bool","name":"isMakerBid","type":"bool"},{"indexed":false,"internalType":"address","name":"implementation","type":"address"}],"name":"NewStrategy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"orderNonces","type":"uint256[]"}],"name":"OrderNoncesCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"strategyId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isActive","type":"bool"},{"indexed":false,"internalType":"uint16","name":"standardProtocolFeeBp","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"minTotalFeeBp","type":"uint16"}],"name":"StrategyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"subsetNonces","type":"uint256[]"}],"name":"SubsetNoncesCancelled","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"uint256","name":"orderNonce","type":"uint256"},{"internalType":"bool","name":"isNonceInvalidated","type":"bool"}],"indexed":false,"internalType":"struct ILooksRareProtocol.NonceInvalidationParameters","name":"nonceInvalidationParameters","type":"tuple"},{"indexed":false,"internalType":"address","name":"askUser","type":"address"},{"indexed":false,"internalType":"address","name":"bidUser","type":"address"},{"indexed":false,"internalType":"uint256","name":"strategyId","type":"uint256"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"itemIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":false,"internalType":"address[2]","name":"feeRecipients","type":"address[2]"},{"indexed":false,"internalType":"uint256[3]","name":"feeAmounts","type":"uint256[3]"}],"name":"TakerAsk","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"uint256","name":"orderNonce","type":"uint256"},{"internalType":"bool","name":"isNonceInvalidated","type":"bool"}],"indexed":false,"internalType":"struct ILooksRareProtocol.NonceInvalidationParameters","name":"nonceInvalidationParameters","type":"tuple"},{"indexed":false,"internalType":"address","name":"bidUser","type":"address"},{"indexed":false,"internalType":"address","name":"bidRecipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"strategyId","type":"uint256"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"itemIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":false,"internalType":"address[2]","name":"feeRecipients","type":"address[2]"},{"indexed":false,"internalType":"uint256[3]","name":"feeAmounts","type":"uint256[3]"}],"name":"TakerBid","type":"event"},{"inputs":[],"name":"MAGIC_VALUE_ORDER_NONCE_EXECUTED","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"standardProtocolFeeBp","type":"uint16"},{"internalType":"uint16","name":"minTotalFeeBp","type":"uint16"},{"internalType":"uint16","name":"maxProtocolFeeBp","type":"uint16"},{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"bool","name":"isMakerBid","type":"bool"},{"internalType":"address","name":"implementation","type":"address"}],"name":"addStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"affiliateController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"affiliateRates","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"orderNonces","type":"uint256[]"}],"name":"cancelOrderNonces","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelOwnershipTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"subsetNonces","type":"uint256[]"}],"name":"cancelSubsetNonces","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"confirmOwnershipRenouncement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"confirmOwnershipTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"creatorFeeManager","outputs":[{"internalType":"contract ICreatorFeeManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bytes","name":"additionalParameters","type":"bytes"}],"internalType":"struct OrderStructs.Taker[]","name":"takerBids","type":"tuple[]"},{"components":[{"internalType":"enum QuoteType","name":"quoteType","type":"uint8"},{"internalType":"uint256","name":"globalNonce","type":"uint256"},{"internalType":"uint256","name":"subsetNonce","type":"uint256"},{"internalType":"uint256","name":"orderNonce","type":"uint256"},{"internalType":"uint256","name":"strategyId","type":"uint256"},{"internalType":"enum CollectionType","name":"collectionType","type":"uint8"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256[]","name":"itemIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"additionalParameters","type":"bytes"}],"internalType":"struct OrderStructs.Maker[]","name":"makerAsks","type":"tuple[]"},{"internalType":"bytes[]","name":"makerSignatures","type":"bytes[]"},{"components":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"value","type":"bytes32"},{"internalType":"enum OrderStructs.MerkleTreeNodePosition","name":"position","type":"uint8"}],"internalType":"struct OrderStructs.MerkleTreeNode[]","name":"proof","type":"tuple[]"}],"internalType":"struct OrderStructs.MerkleTree[]","name":"merkleTrees","type":"tuple[]"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bool","name":"isAtomic","type":"bool"}],"name":"executeMultipleTakerBids","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bytes","name":"additionalParameters","type":"bytes"}],"internalType":"struct OrderStructs.Taker","name":"takerAsk","type":"tuple"},{"components":[{"internalType":"enum QuoteType","name":"quoteType","type":"uint8"},{"internalType":"uint256","name":"globalNonce","type":"uint256"},{"internalType":"uint256","name":"subsetNonce","type":"uint256"},{"internalType":"uint256","name":"orderNonce","type":"uint256"},{"internalType":"uint256","name":"strategyId","type":"uint256"},{"internalType":"enum CollectionType","name":"collectionType","type":"uint8"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256[]","name":"itemIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"additionalParameters","type":"bytes"}],"internalType":"struct OrderStructs.Maker","name":"makerBid","type":"tuple"},{"internalType":"bytes","name":"makerSignature","type":"bytes"},{"components":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"value","type":"bytes32"},{"internalType":"enum OrderStructs.MerkleTreeNodePosition","name":"position","type":"uint8"}],"internalType":"struct OrderStructs.MerkleTreeNode[]","name":"proof","type":"tuple[]"}],"internalType":"struct OrderStructs.MerkleTree","name":"merkleTree","type":"tuple"},{"internalType":"address","name":"affiliate","type":"address"}],"name":"executeTakerAsk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bytes","name":"additionalParameters","type":"bytes"}],"internalType":"struct OrderStructs.Taker","name":"takerBid","type":"tuple"},{"components":[{"internalType":"enum QuoteType","name":"quoteType","type":"uint8"},{"internalType":"uint256","name":"globalNonce","type":"uint256"},{"internalType":"uint256","name":"subsetNonce","type":"uint256"},{"internalType":"uint256","name":"orderNonce","type":"uint256"},{"internalType":"uint256","name":"strategyId","type":"uint256"},{"internalType":"enum CollectionType","name":"collectionType","type":"uint8"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256[]","name":"itemIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"additionalParameters","type":"bytes"}],"internalType":"struct OrderStructs.Maker","name":"makerAsk","type":"tuple"},{"internalType":"bytes","name":"makerSignature","type":"bytes"},{"components":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"value","type":"bytes32"},{"internalType":"enum OrderStructs.MerkleTreeNodePosition","name":"position","type":"uint8"}],"internalType":"struct OrderStructs.MerkleTreeNode[]","name":"proof","type":"tuple[]"}],"internalType":"struct OrderStructs.MerkleTree","name":"merkleTree","type":"tuple"},{"internalType":"address","name":"affiliate","type":"address"}],"name":"executeTakerBid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"uint256","name":"proofLength","type":"uint256"}],"name":"hashBatchOrder","outputs":[{"internalType":"bytes32","name":"batchOrderHash","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bool","name":"bid","type":"bool"},{"internalType":"bool","name":"ask","type":"bool"}],"name":"incrementBidAskNonces","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initiateOwnershipRenouncement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPotentialOwner","type":"address"}],"name":"initiateOwnershipTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isAffiliateProgramActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isCurrencyAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxCreatorFeeBp","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownershipStatus","outputs":[{"internalType":"enum IOwnableTwoSteps.Status","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"potentialOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bytes","name":"additionalParameters","type":"bytes"}],"internalType":"struct OrderStructs.Taker","name":"takerBid","type":"tuple"},{"components":[{"internalType":"enum QuoteType","name":"quoteType","type":"uint8"},{"internalType":"uint256","name":"globalNonce","type":"uint256"},{"internalType":"uint256","name":"subsetNonce","type":"uint256"},{"internalType":"uint256","name":"orderNonce","type":"uint256"},{"internalType":"uint256","name":"strategyId","type":"uint256"},{"internalType":"enum CollectionType","name":"collectionType","type":"uint8"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256[]","name":"itemIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"additionalParameters","type":"bytes"}],"internalType":"struct OrderStructs.Maker","name":"makerAsk","type":"tuple"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"restrictedExecuteTakerBid","outputs":[{"internalType":"uint256","name":"protocolFeeAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"strategyInfo","outputs":[{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint16","name":"standardProtocolFeeBp","type":"uint16"},{"internalType":"uint16","name":"minTotalFeeBp","type":"uint16"},{"internalType":"uint16","name":"maxProtocolFeeBp","type":"uint16"},{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"bool","name":"isMakerBid","type":"bool"},{"internalType":"address","name":"implementation","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transferManager","outputs":[{"internalType":"contract TransferManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAffiliateController","type":"address"}],"name":"updateAffiliateController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isActive","type":"bool"}],"name":"updateAffiliateProgramStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"uint256","name":"bp","type":"uint256"}],"name":"updateAffiliateRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newCreatorFeeManager","type":"address"}],"name":"updateCreatorFeeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"currency","type":"address"},{"internalType":"bool","name":"isAllowed","type":"bool"}],"name":"updateCurrencyStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateDomainSeparator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newGasLimitETHTransfer","type":"uint256"}],"name":"updateETHGasLimitForTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"newMaxCreatorFeeBp","type":"uint16"}],"name":"updateMaxCreatorFeeBp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newProtocolFeeRecipient","type":"address"}],"name":"updateProtocolFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"strategyId","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint16","name":"newStandardProtocolFee","type":"uint16"},{"internalType":"uint16","name":"newMinTotalFee","type":"uint16"}],"name":"updateStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userBidAskNonces","outputs":[{"internalType":"uint256","name":"bidNonce","type":"uint256"},{"internalType":"uint256","name":"askNonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userOrderNonce","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userSubsetNonce","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]