文件 1 的 16:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 2 的 16:IERC1155.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC1155 is IERC165 {
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;
}
文件 3 的 16:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 4 的 16:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, 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 sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 5 的 16:IERC721.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
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
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
文件 6 的 16:IExchangeKind.sol
pragma solidity ^0.8.9;
enum ExchangeKind {
WYVERN_V23,
LOOKS_RARE,
ZEROEX_V4,
FOUNDATION,
X2Y2,
SEAPORT
}
文件 7 的 16:IFoundation.sol
pragma solidity ^0.8.9;
interface IFoundation {
function buyV2(
address nftContract,
uint256 tokenId,
uint256 maxPrice,
address referrer
) external payable;
}
文件 8 的 16:ILooksRare.sol
pragma solidity ^0.8.9;
interface IOrderTypes {
struct MakerOrder {
bool isOrderAsk;
address signer;
address collection;
uint256 price;
uint256 tokenId;
uint256 amount;
address strategy;
address currency;
uint256 nonce;
uint256 startTime;
uint256 endTime;
uint256 minPercentageToAsk;
bytes params;
uint8 v;
bytes32 r;
bytes32 s;
}
struct TakerOrder {
bool isOrderAsk;
address taker;
uint256 price;
uint256 tokenId;
uint256 minPercentageToAsk;
bytes params;
}
}
interface ILooksRare {
function transferSelectorNFT() external view returns (address);
function matchAskWithTakerBidUsingETHAndWETH(
IOrderTypes.TakerOrder calldata takerBid,
IOrderTypes.MakerOrder calldata makerAsk
) external payable;
function matchBidWithTakerAsk(
IOrderTypes.TakerOrder calldata takerAsk,
IOrderTypes.MakerOrder calldata makerBid
) external;
}
interface ILooksRareTransferSelectorNFT {
function TRANSFER_MANAGER_ERC721() external view returns (address);
function TRANSFER_MANAGER_ERC1155() external view returns (address);
}
文件 9 的 16:ISeaport.sol
pragma solidity ^0.8.9;
interface ISeaport {
enum OrderType {
FULL_OPEN,
PARTIAL_OPEN,
FULL_RESTRICTED,
PARTIAL_RESTRICTED
}
enum ItemType {
NATIVE,
ERC20,
ERC721,
ERC1155,
ERC721_WITH_CRITERIA,
ERC1155_WITH_CRITERIA
}
enum Side {
OFFER,
CONSIDERATION
}
struct OfferItem {
ItemType itemType;
address token;
uint256 identifierOrCriteria;
uint256 startAmount;
uint256 endAmount;
}
struct ConsiderationItem {
ItemType itemType;
address token;
uint256 identifierOrCriteria;
uint256 startAmount;
uint256 endAmount;
address recipient;
}
struct ReceivedItem {
ItemType itemType;
address token;
uint256 identifier;
uint256 amount;
address recipient;
}
struct OrderParameters {
address offerer;
address zone;
OfferItem[] offer;
ConsiderationItem[] consideration;
OrderType orderType;
uint256 startTime;
uint256 endTime;
bytes32 zoneHash;
uint256 salt;
bytes32 conduitKey;
uint256 totalOriginalConsiderationItems;
}
struct AdvancedOrder {
OrderParameters parameters;
uint120 numerator;
uint120 denominator;
bytes signature;
bytes extraData;
}
struct CriteriaResolver {
uint256 orderIndex;
Side side;
uint256 index;
uint256 identifier;
bytes32[] criteriaProof;
}
struct FulfillmentComponent {
uint256 orderIndex;
uint256 itemIndex;
}
struct Fulfillment {
FulfillmentComponent[] offerComponents;
FulfillmentComponent[] considerationComponents;
}
struct Execution {
ReceivedItem item;
address offerer;
bytes32 conduitKey;
}
function fulfillAdvancedOrder(
AdvancedOrder calldata advancedOrder,
CriteriaResolver[] calldata criteriaResolvers,
bytes32 fulfillerConduitKey,
address recipient
) external payable returns (bool fulfilled);
function fulfillAvailableAdvancedOrders(
AdvancedOrder[] memory advancedOrders,
CriteriaResolver[] calldata criteriaResolvers,
FulfillmentComponent[][] calldata offerFulfillments,
FulfillmentComponent[][] calldata considerationFulfillments,
bytes32 fulfillerConduitKey,
address recipient,
uint256 maximumFulfilled
)
external
payable
returns (bool[] memory availableOrders, Execution[] memory executions);
function matchAdvancedOrders(
AdvancedOrder[] calldata advancedOrders,
CriteriaResolver[] calldata criteriaResolvers,
Fulfillment[] calldata fulfillments
) external payable returns (Execution[] memory executions);
}
文件 10 的 16:IWETH.sol
pragma solidity ^0.8.9;
interface IWETH {
function deposit() external payable;
function withdraw(uint256 amount) external;
}
文件 11 的 16:IWyvernV23.sol
pragma solidity ^0.8.9;
interface IWyvernV23 {
function registry() external view returns (address);
function tokenTransferProxy() external view returns (address);
function atomicMatch_(
address[14] calldata addrs,
uint256[18] calldata uints,
uint8[8] calldata feeMethodsSidesKindsHowToCalls,
bytes calldata calldataBuy,
bytes calldata calldataSell,
bytes calldata replacementPatternBuy,
bytes calldata replacementPatternSell,
bytes calldata staticExtradataBuy,
bytes calldata staticExtradataSell,
uint8[2] calldata vs,
bytes32[5] calldata rssMetadata
) external payable;
}
interface IWyvernV23ProxyRegistry {
function registerProxy() external;
function proxies(address user) external view returns (address);
}
文件 12 的 16:IX2Y2.sol
pragma solidity ^0.8.9;
interface IX2Y2 {
struct OrderItem {
uint256 price;
bytes data;
}
struct Order {
uint256 salt;
address user;
uint256 network;
uint256 intent;
uint256 delegateType;
uint256 deadline;
address currency;
bytes dataMask;
OrderItem[] items;
bytes32 r;
bytes32 s;
uint8 v;
uint8 signVersion;
}
struct SettleShared {
uint256 salt;
uint256 deadline;
uint256 amountToEth;
uint256 amountToWeth;
address user;
bool canFail;
}
struct Fee {
uint256 percentage;
address to;
}
enum Op {
INVALID,
COMPLETE_SELL_OFFER,
COMPLETE_BUY_OFFER,
CANCEL_OFFER,
BID,
COMPLETE_AUCTION,
REFUND_AUCTION,
REFUND_AUCTION_STUCK_ITEM
}
struct SettleDetail {
Op op;
uint256 orderIdx;
uint256 itemIdx;
uint256 price;
bytes32 itemHash;
address executionDelegate;
bytes dataReplacement;
uint256 bidIncentivePct;
uint256 aucMinIncrementPct;
uint256 aucIncDurationSecs;
Fee[] fees;
}
struct RunInput {
Order[] orders;
SettleDetail[] details;
SettleShared shared;
bytes32 r;
bytes32 s;
uint8 v;
}
function run(RunInput calldata input) external payable;
}
文件 13 的 16:IZeroExV4.sol
pragma solidity ^0.8.9;
interface IZeroExV4 {
struct Property {
address propertyValidator;
bytes propertyData;
}
struct Fee {
address recipient;
uint256 amount;
bytes feeData;
}
struct ERC721Order {
uint8 direction;
address maker;
address taker;
uint256 expiry;
uint256 nonce;
address erc20Token;
uint256 erc20TokenAmount;
Fee[] fees;
address erc721Token;
uint256 erc721TokenId;
Property[] erc721TokenProperties;
}
struct ERC1155Order {
uint8 direction;
address maker;
address taker;
uint256 expiry;
uint256 nonce;
address erc20Token;
uint256 erc20TokenAmount;
Fee[] fees;
address erc1155Token;
uint256 erc1155TokenId;
Property[] erc1155TokenProperties;
uint128 erc1155TokenAmount;
}
struct Signature {
uint8 signatureType;
uint8 v;
bytes32 r;
bytes32 s;
}
function buyERC721(
ERC721Order calldata sellOrder,
Signature calldata signature,
bytes memory callbackData
) external payable;
function batchBuyERC721s(
ERC721Order[] calldata sellOrders,
Signature[] calldata signatures,
bytes[] calldata callbackData,
bool revertIfIncomplete
) external payable returns (bool[] memory);
function sellERC721(
ERC721Order calldata buyOrder,
Signature calldata signature,
uint256 erc721TokenId,
bool unwrapNativeToken,
bytes memory callbackData
) external;
function buyERC1155(
ERC1155Order calldata sellOrder,
Signature calldata signature,
uint128 erc1155BuyAmount,
bytes calldata callbackData
) external payable;
function batchBuyERC1155s(
ERC1155Order[] calldata sellOrders,
Signature[] calldata signatures,
uint128[] calldata erc1155FillAmounts,
bytes[] calldata callbackData,
bool revertIfIncomplete
) external payable returns (bool[] memory successes);
function sellERC1155(
ERC1155Order calldata buyOrder,
Signature calldata signature,
uint256 erc1155TokenId,
uint128 erc1155SellAmount,
bool unwrapNativeToken,
bytes calldata callbackData
) external;
}
文件 14 的 16:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 15 的 16:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 16 的 16:ReservoirV5_0_0.sol
pragma solidity ^0.8.9;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import {ExchangeKind} from "./interfaces/IExchangeKind.sol";
import {IWETH} from "./interfaces/IWETH.sol";
import {IFoundation} from "./interfaces/IFoundation.sol";
import {ILooksRare, ILooksRareTransferSelectorNFT} from "./interfaces/ILooksRare.sol";
import {ISeaport} from "./interfaces/ISeaport.sol";
import {IWyvernV23, IWyvernV23ProxyRegistry} from "./interfaces/IWyvernV23.sol";
import {IX2Y2} from "./interfaces/IX2Y2.sol";
import {IZeroExV4} from "./interfaces/IZeroExV4.sol";
contract ReservoirV5_0_0 is Ownable, ReentrancyGuard {
address public immutable weth;
address public immutable looksRare;
address public immutable looksRareTransferManagerERC721;
address public immutable looksRareTransferManagerERC1155;
address public immutable wyvernV23;
address public immutable wyvernV23Proxy;
address public immutable zeroExV4;
address public immutable foundation;
address public immutable x2y2;
address public immutable x2y2ERC721Delegate;
address public immutable seaport;
error UnexpectedOwnerOrBalance();
error UnexpectedSelector();
error UnsuccessfulCall();
error UnsuccessfulFill();
error UnsuccessfulPayment();
error UnsupportedExchange();
constructor(
address wethAddress,
address looksRareAddress,
address wyvernV23Address,
address zeroExV4Address,
address foundationAddress,
address x2y2Address,
address x2y2ERC721DelegateAddress,
address seaportAddress
) {
weth = wethAddress;
looksRare = looksRareAddress;
address transferSelectorNFT = ILooksRare(looksRare)
.transferSelectorNFT();
looksRareTransferManagerERC721 = ILooksRareTransferSelectorNFT(
transferSelectorNFT
).TRANSFER_MANAGER_ERC721();
looksRareTransferManagerERC1155 = ILooksRareTransferSelectorNFT(
transferSelectorNFT
).TRANSFER_MANAGER_ERC1155();
wyvernV23 = wyvernV23Address;
address proxyRegistry = IWyvernV23(wyvernV23).registry();
IWyvernV23ProxyRegistry(proxyRegistry).registerProxy();
wyvernV23Proxy = IWyvernV23ProxyRegistry(proxyRegistry).proxies(
address(this)
);
IERC20(weth).approve(
IWyvernV23(wyvernV23).tokenTransferProxy(),
type(uint256).max
);
zeroExV4 = zeroExV4Address;
foundation = foundationAddress;
x2y2 = x2y2Address;
x2y2ERC721Delegate = x2y2ERC721DelegateAddress;
seaport = seaportAddress;
IERC20(weth).approve(seaport, type(uint256).max);
}
receive() external payable {
}
function makeCalls(
address[] calldata targets,
bytes[] calldata data,
uint256[] calldata values
) external payable onlyOwner nonReentrant {
bool success;
uint256 length = targets.length;
for (uint256 i = 0; i < length; ) {
(success, ) = payable(targets[i]).call{value: values[i]}(data[i]);
if (!success) {
revert UnsuccessfulCall();
}
unchecked {
++i;
}
}
}
function singleERC721ListingFill(
bytes calldata data,
ExchangeKind exchangeKind,
address collection,
uint256 tokenId,
address receiver,
address feeRecipient,
uint16 feeBps
) external payable nonReentrant {
bytes4 selector = bytes4(data[:4]);
address target;
if (exchangeKind == ExchangeKind.SEAPORT) {
target = seaport;
if (
selector != ISeaport.fulfillAdvancedOrder.selector &&
selector != ISeaport.matchAdvancedOrders.selector
) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.WYVERN_V23) {
target = wyvernV23;
if (selector != IWyvernV23.atomicMatch_.selector) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.LOOKS_RARE) {
target = looksRare;
if (
selector !=
ILooksRare.matchAskWithTakerBidUsingETHAndWETH.selector
) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.ZEROEX_V4) {
target = zeroExV4;
if (selector != IZeroExV4.buyERC721.selector) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.X2Y2) {
target = x2y2;
if (selector != IX2Y2.run.selector) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.FOUNDATION) {
target = foundation;
if (selector != IFoundation.buyV2.selector) {
revert UnexpectedSelector();
}
} else {
revert UnsupportedExchange();
}
uint256 payment = (10000 * msg.value) / (10000 + feeBps);
(bool success, ) = target.call{value: payment}(data);
if (!success) {
revert UnsuccessfulFill();
}
if (
exchangeKind != ExchangeKind.SEAPORT &&
exchangeKind != ExchangeKind.WYVERN_V23
) {
IERC721(collection).safeTransferFrom(
address(this),
receiver,
tokenId
);
}
uint256 fee = msg.value - payment;
if (fee > 0) {
(success, ) = payable(feeRecipient).call{value: fee}("");
if (!success) {
revert UnsuccessfulPayment();
}
}
}
function singleERC721ListingFillWithPrecheck(
bytes calldata data,
ExchangeKind exchangeKind,
address collection,
uint256 tokenId,
address receiver,
address expectedOwner,
address feeRecipient,
uint16 feeBps
) external payable nonReentrant {
if (
expectedOwner != address(0) &&
IERC721(collection).ownerOf(tokenId) != expectedOwner
) {
revert UnexpectedOwnerOrBalance();
}
bytes4 selector = bytes4(data[:4]);
address target;
if (exchangeKind == ExchangeKind.SEAPORT) {
target = seaport;
if (
selector != ISeaport.fulfillAdvancedOrder.selector &&
selector != ISeaport.matchAdvancedOrders.selector
) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.WYVERN_V23) {
target = wyvernV23;
if (selector != IWyvernV23.atomicMatch_.selector) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.LOOKS_RARE) {
target = looksRare;
if (
selector !=
ILooksRare.matchAskWithTakerBidUsingETHAndWETH.selector
) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.ZEROEX_V4) {
target = zeroExV4;
if (selector != IZeroExV4.buyERC721.selector) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.X2Y2) {
target = x2y2;
if (selector != IX2Y2.run.selector) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.FOUNDATION) {
target = foundation;
if (selector != IFoundation.buyV2.selector) {
revert UnexpectedSelector();
}
} else {
revert UnsupportedExchange();
}
uint256 payment = (10000 * msg.value) / (10000 + feeBps);
(bool success, ) = target.call{value: payment}(data);
if (!success) {
revert UnsuccessfulFill();
}
if (
exchangeKind != ExchangeKind.SEAPORT &&
exchangeKind != ExchangeKind.WYVERN_V23
) {
IERC721(collection).safeTransferFrom(
address(this),
receiver,
tokenId
);
}
uint256 fee = msg.value - payment;
if (fee > 0) {
(success, ) = payable(feeRecipient).call{value: fee}("");
if (!success) {
revert UnsuccessfulPayment();
}
}
}
function batchERC721ListingFill(
bytes calldata data,
address[] calldata collections,
uint256[] calldata tokenIds,
address receiver,
address feeRecipient,
uint16 feeBps
) external payable nonReentrant {
if (bytes4(data[:4]) != IZeroExV4.batchBuyERC721s.selector) {
revert UnexpectedSelector();
}
uint256 payment = (10000 * msg.value) / (10000 + feeBps);
(bool success, ) = zeroExV4.call{value: payment}(data);
if (!success) {
revert UnsuccessfulFill();
}
uint256 length = collections.length;
for (uint256 i = 0; i < length; ) {
IERC721(collections[i]).safeTransferFrom(
address(this),
receiver,
tokenIds[i]
);
unchecked {
++i;
}
}
uint256 fee = msg.value - payment;
if (fee > 0) {
(success, ) = payable(feeRecipient).call{value: fee}("");
if (!success) {
revert UnsuccessfulPayment();
}
}
}
function singleERC721BidFill(
bytes calldata data,
ExchangeKind exchangeKind,
address collection,
address receiver,
bool unwrapWeth
) external payable nonReentrant {
bytes4 selector = bytes4(data[:4]);
address target;
address operator;
if (exchangeKind == ExchangeKind.SEAPORT) {
target = seaport;
operator = seaport;
if (
selector != ISeaport.fulfillAdvancedOrder.selector &&
selector != ISeaport.matchAdvancedOrders.selector
) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.WYVERN_V23) {
target = wyvernV23;
operator = wyvernV23Proxy;
if (selector != IWyvernV23.atomicMatch_.selector) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.LOOKS_RARE) {
target = looksRare;
operator = looksRareTransferManagerERC721;
if (selector != ILooksRare.matchBidWithTakerAsk.selector) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.ZEROEX_V4) {
target = zeroExV4;
operator = zeroExV4;
if (selector != IZeroExV4.sellERC721.selector) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.X2Y2) {
target = x2y2;
operator = x2y2ERC721Delegate;
if (selector != IX2Y2.run.selector) {
revert UnexpectedSelector();
}
} else {
revert UnsupportedExchange();
}
bool isApproved = IERC721(collection).isApprovedForAll(
address(this),
operator
);
if (!isApproved) {
IERC721(collection).setApprovalForAll(operator, true);
}
uint256 wethBalanceBefore = IERC20(weth).balanceOf(address(this));
(bool success, ) = target.call{value: msg.value}(data);
if (!success) {
revert UnsuccessfulPayment();
}
uint256 balance = IERC20(weth).balanceOf(address(this)) -
wethBalanceBefore;
if (unwrapWeth) {
IWETH(weth).withdraw(balance);
(success, ) = payable(receiver).call{value: balance}("");
if (!success) {
revert UnsuccessfulPayment();
}
} else {
IERC20(weth).transfer(receiver, balance);
}
}
function singleERC1155ListingFill(
bytes calldata data,
ExchangeKind exchangeKind,
address collection,
uint256 tokenId,
uint256 amount,
address receiver,
address feeRecipient,
uint16 feeBps
) external payable nonReentrant {
bytes4 selector = bytes4(data[:4]);
address target;
if (exchangeKind == ExchangeKind.SEAPORT) {
target = seaport;
if (
selector != ISeaport.fulfillAdvancedOrder.selector &&
selector != ISeaport.matchAdvancedOrders.selector
) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.WYVERN_V23) {
target = wyvernV23;
if (selector != IWyvernV23.atomicMatch_.selector) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.LOOKS_RARE) {
target = looksRare;
if (
selector !=
ILooksRare.matchAskWithTakerBidUsingETHAndWETH.selector
) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.ZEROEX_V4) {
target = zeroExV4;
if (selector != IZeroExV4.buyERC1155.selector) {
revert UnexpectedSelector();
}
} else {
revert UnsupportedExchange();
}
uint256 payment = (10000 * msg.value) / (10000 + feeBps);
(bool success, ) = target.call{value: payment}(data);
if (!success) {
revert UnsuccessfulFill();
}
if (
exchangeKind != ExchangeKind.SEAPORT &&
exchangeKind != ExchangeKind.WYVERN_V23
) {
IERC1155(collection).safeTransferFrom(
address(this),
receiver,
tokenId,
amount,
""
);
}
uint256 fee = msg.value - payment;
if (fee > 0) {
(success, ) = payable(feeRecipient).call{value: fee}("");
if (!success) {
revert UnsuccessfulPayment();
}
}
}
function singleERC1155ListingFillWithPrecheck(
bytes calldata data,
ExchangeKind exchangeKind,
address collection,
uint256 tokenId,
uint256 amount,
address receiver,
address expectedOwner,
address feeRecipient,
uint16 feeBps
) external payable nonReentrant {
if (
expectedOwner != address(0) &&
IERC1155(collection).balanceOf(expectedOwner, tokenId) < amount
) {
revert UnexpectedOwnerOrBalance();
}
bytes4 selector = bytes4(data[:4]);
address target;
if (exchangeKind == ExchangeKind.SEAPORT) {
target = seaport;
if (
selector != ISeaport.fulfillAdvancedOrder.selector &&
selector != ISeaport.matchAdvancedOrders.selector
) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.WYVERN_V23) {
target = wyvernV23;
if (selector != IWyvernV23.atomicMatch_.selector) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.LOOKS_RARE) {
target = looksRare;
if (
selector !=
ILooksRare.matchAskWithTakerBidUsingETHAndWETH.selector
) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.ZEROEX_V4) {
target = zeroExV4;
if (selector != IZeroExV4.buyERC1155.selector) {
revert UnexpectedSelector();
}
} else {
revert UnsupportedExchange();
}
uint256 payment = (10000 * msg.value) / (10000 + feeBps);
(bool success, ) = target.call{value: payment}(data);
if (!success) {
revert UnsuccessfulFill();
}
if (
exchangeKind != ExchangeKind.SEAPORT &&
exchangeKind != ExchangeKind.WYVERN_V23
) {
IERC1155(collection).safeTransferFrom(
address(this),
receiver,
tokenId,
amount,
""
);
}
uint256 fee = msg.value - payment;
if (fee > 0) {
(success, ) = payable(feeRecipient).call{value: fee}("");
if (!success) {
revert UnsuccessfulPayment();
}
}
}
function batchERC1155ListingFill(
bytes calldata data,
address[] calldata collections,
uint256[] calldata tokenIds,
uint256[] calldata amounts,
address receiver,
address feeRecipient,
uint16 feeBps
) external payable nonReentrant {
if (bytes4(data[:4]) != IZeroExV4.batchBuyERC1155s.selector) {
revert UnexpectedSelector();
}
uint256 payment = (10000 * msg.value) / (10000 + feeBps);
(bool success, ) = zeroExV4.call{value: payment}(data);
if (!success) {
revert UnsuccessfulFill();
}
{
uint256 length = collections.length;
for (uint256 i = 0; i < length; ) {
IERC1155(collections[i]).safeTransferFrom(
address(this),
receiver,
tokenIds[i],
amounts[i],
""
);
unchecked {
++i;
}
}
}
uint256 fee = msg.value - payment;
if (fee > 0) {
(success, ) = payable(feeRecipient).call{value: fee}("");
if (!success) {
revert UnsuccessfulPayment();
}
}
}
function singleERC1155BidFill(
bytes calldata data,
ExchangeKind exchangeKind,
address collection,
address receiver,
bool unwrapWeth
) external payable nonReentrant {
bytes4 selector = bytes4(data[:4]);
address target;
address operator;
if (exchangeKind == ExchangeKind.SEAPORT) {
target = seaport;
operator = seaport;
if (
selector != ISeaport.fulfillAdvancedOrder.selector &&
selector != ISeaport.matchAdvancedOrders.selector
) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.WYVERN_V23) {
target = wyvernV23;
operator = wyvernV23Proxy;
if (selector != IWyvernV23.atomicMatch_.selector) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.LOOKS_RARE) {
target = looksRare;
operator = looksRareTransferManagerERC1155;
if (selector != ILooksRare.matchBidWithTakerAsk.selector) {
revert UnexpectedSelector();
}
} else if (exchangeKind == ExchangeKind.ZEROEX_V4) {
target = zeroExV4;
operator = zeroExV4;
if (selector != IZeroExV4.sellERC1155.selector) {
revert UnexpectedSelector();
}
} else {
revert UnsupportedExchange();
}
bool isApproved = IERC1155(collection).isApprovedForAll(
address(this),
operator
);
if (!isApproved) {
IERC1155(collection).setApprovalForAll(operator, true);
}
uint256 wethBalanceBefore = IERC20(weth).balanceOf(address(this));
(bool success, ) = target.call{value: msg.value}(data);
if (!success) {
revert UnsuccessfulFill();
}
uint256 balance = IERC20(weth).balanceOf(address(this)) -
wethBalanceBefore;
if (unwrapWeth) {
IWETH(weth).withdraw(balance);
(success, ) = payable(receiver).call{value: balance}("");
if (!success) {
revert UnsuccessfulPayment();
}
} else {
IERC20(weth).transfer(receiver, balance);
}
}
function multiListingFill(
bytes[] calldata data,
uint256[] calldata values,
bool revertIfIncomplete
) external payable {
bool success;
uint256 balanceBefore = address(this).balance - msg.value;
uint256 length = data.length;
for (uint256 i = 0; i < length; ) {
(success, ) = address(this).call{value: values[i]}(data[i]);
if (revertIfIncomplete && !success) {
revert UnsuccessfulFill();
}
unchecked {
++i;
}
}
uint256 balanceAfter = address(this).balance;
if (balanceAfter > balanceBefore) {
(success, ) = msg.sender.call{value: balanceAfter - balanceBefore}(
""
);
if (!success) {
revert UnsuccessfulPayment();
}
}
}
function onERC721Received(
address,
address,
uint256,
bytes calldata data
) external returns (bytes4) {
if (data.length == 0) {
return this.onERC721Received.selector;
}
bytes4 selector = bytes4(data[:4]);
if (selector != this.singleERC721BidFill.selector) {
revert UnexpectedSelector();
}
(bool success, ) = address(this).call(data);
if (!success) {
revert UnsuccessfulFill();
}
return this.onERC721Received.selector;
}
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes calldata data
) external returns (bytes4) {
if (data.length == 0) {
return this.onERC1155Received.selector;
}
bytes4 selector = bytes4(data[:4]);
if (selector != this.singleERC1155BidFill.selector) {
revert UnexpectedSelector();
}
(bool success, ) = address(this).call(data);
if (!success) {
revert UnsuccessfulFill();
}
return this.onERC1155Received.selector;
}
}
{
"compilationTarget": {
"contracts/router/ReservoirV5_0_0.sol": "ReservoirV5_0_0"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"wethAddress","type":"address"},{"internalType":"address","name":"looksRareAddress","type":"address"},{"internalType":"address","name":"wyvernV23Address","type":"address"},{"internalType":"address","name":"zeroExV4Address","type":"address"},{"internalType":"address","name":"foundationAddress","type":"address"},{"internalType":"address","name":"x2y2Address","type":"address"},{"internalType":"address","name":"x2y2ERC721DelegateAddress","type":"address"},{"internalType":"address","name":"seaportAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"UnexpectedOwnerOrBalance","type":"error"},{"inputs":[],"name":"UnexpectedSelector","type":"error"},{"inputs":[],"name":"UnsuccessfulCall","type":"error"},{"inputs":[],"name":"UnsuccessfulFill","type":"error"},{"inputs":[],"name":"UnsuccessfulPayment","type":"error"},{"inputs":[],"name":"UnsupportedExchange","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"address[]","name":"collections","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"feeRecipient","type":"address"},{"internalType":"uint16","name":"feeBps","type":"uint16"}],"name":"batchERC1155ListingFill","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"address[]","name":"collections","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"feeRecipient","type":"address"},{"internalType":"uint16","name":"feeBps","type":"uint16"}],"name":"batchERC721ListingFill","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"foundation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"looksRare","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"looksRareTransferManagerERC1155","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"looksRareTransferManagerERC721","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"makeCalls","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bool","name":"revertIfIncomplete","type":"bool"}],"name":"multiListingFill","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"seaport","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum ExchangeKind","name":"exchangeKind","type":"uint8"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bool","name":"unwrapWeth","type":"bool"}],"name":"singleERC1155BidFill","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum ExchangeKind","name":"exchangeKind","type":"uint8"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"feeRecipient","type":"address"},{"internalType":"uint16","name":"feeBps","type":"uint16"}],"name":"singleERC1155ListingFill","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum ExchangeKind","name":"exchangeKind","type":"uint8"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"expectedOwner","type":"address"},{"internalType":"address","name":"feeRecipient","type":"address"},{"internalType":"uint16","name":"feeBps","type":"uint16"}],"name":"singleERC1155ListingFillWithPrecheck","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum ExchangeKind","name":"exchangeKind","type":"uint8"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bool","name":"unwrapWeth","type":"bool"}],"name":"singleERC721BidFill","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum ExchangeKind","name":"exchangeKind","type":"uint8"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"feeRecipient","type":"address"},{"internalType":"uint16","name":"feeBps","type":"uint16"}],"name":"singleERC721ListingFill","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum ExchangeKind","name":"exchangeKind","type":"uint8"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"expectedOwner","type":"address"},{"internalType":"address","name":"feeRecipient","type":"address"},{"internalType":"uint16","name":"feeBps","type":"uint16"}],"name":"singleERC721ListingFillWithPrecheck","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wyvernV23","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wyvernV23Proxy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"x2y2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"x2y2ERC721Delegate","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"zeroExV4","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]