编译器
0.8.19+commit.7dd6d404
文件 1 的 23:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 23:ConduitSignatureVerifier.sol
pragma solidity 0.8.19;
import "../lib/Signing.sol";
abstract contract ConduitSignatureVerifier {
bytes32 constant EIP712DOMAIN_TYPEHASH =
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
bytes32 constant BID_TYPEHASH =
keccak256(
"Bid(uint256 id,uint256 price,address tokenAddress,address collection,uint256 orderExpiry,address buyer,uint8 optionType,uint256 strikePrice,uint256 expiry,uint256 expiryAllowance,address optionTokenAddress)"
);
bytes32 constant ASK_TYPEHASH =
keccak256(
"Ask(uint256 id,uint256 price,address tokenAddress,uint256 orderExpiry,address seller,uint256 optionId)"
);
function hashDomain(
WasabiStructs.EIP712Domain memory _eip712Domain
) internal pure returns (bytes32) {
return
keccak256(
abi.encode(
EIP712DOMAIN_TYPEHASH,
keccak256(bytes(_eip712Domain.name)),
keccak256(bytes(_eip712Domain.version)),
_eip712Domain.chainId,
_eip712Domain.verifyingContract
)
);
}
function hashForBid(
WasabiStructs.Bid memory _bid
) public pure returns (bytes32) {
return
keccak256(
abi.encode(
BID_TYPEHASH,
_bid.id,
_bid.price,
_bid.tokenAddress,
_bid.collection,
_bid.orderExpiry,
_bid.buyer,
_bid.optionType,
_bid.strikePrice,
_bid.expiry,
_bid.expiryAllowance,
_bid.optionTokenAddress
)
);
}
function hashForAsk(
WasabiStructs.Ask memory _ask
) public pure returns (bytes32) {
return
keccak256(
abi.encode(
ASK_TYPEHASH,
_ask.id,
_ask.price,
_ask.tokenAddress,
_ask.orderExpiry,
_ask.seller,
_ask.optionId
)
);
}
function getSignerForBid(
WasabiStructs.Bid memory _bid,
bytes memory _signature
) public view returns (address) {
bytes32 domainSeparator = hashDomain(
WasabiStructs.EIP712Domain({
name: "ConduitSignature",
version: "1",
chainId: getChainID(),
verifyingContract: address(this)
})
);
bytes32 digest = keccak256(
abi.encodePacked("\x19\x01", domainSeparator, hashForBid(_bid))
);
return Signing.recoverSigner(digest, _signature);
}
function getSignerForAsk(
WasabiStructs.Ask memory _ask,
bytes memory _signature
) public view returns (address) {
bytes32 domainSeparator = hashDomain(
WasabiStructs.EIP712Domain({
name: "ConduitSignature",
version: "1",
chainId: getChainID(),
verifyingContract: address(this)
})
);
bytes32 digest = keccak256(
abi.encodePacked("\x19\x01", domainSeparator, hashForAsk(_ask))
);
return Signing.recoverSigner(digest, _signature);
}
function verifyBid(
WasabiStructs.Bid memory _bid,
bytes memory _signature,
address _signer
) internal view returns (bool) {
return getSignerForBid(_bid, _signature) == _signer;
}
function verifyAsk(
WasabiStructs.Ask memory _ask,
bytes memory _signature,
address _signer
) internal view returns (bool) {
return getSignerForAsk(_ask, _signature) == _signer;
}
function getChainID() internal view returns (uint256) {
uint256 id;
assembly {
id := chainid()
}
return id;
}
}
文件 3 的 23: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;
}
}
文件 4 的 23:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 5 的 23:ERC721.sol
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
string private _name;
string private _symbol;
mapping(uint256 => address) private _owners;
mapping(address => uint256) private _balances;
mapping(uint256 => address) private _tokenApprovals;
mapping(address => mapping(address => bool)) private _operatorApprovals;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: address zero is not a valid owner");
return _balances[owner];
}
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: invalid token ID");
return owner;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
_requireMinted(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
function _baseURI() internal view virtual returns (string memory) {
return "";
}
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not token owner nor approved for all"
);
_approve(to, tokenId);
}
function getApproved(uint256 tokenId) public view virtual override returns (address) {
_requireMinted(tokenId);
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");
_transfer(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");
_safeTransfer(from, to, tokenId, data);
}
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
}
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
function _safeMint(
address to,
uint256 tokenId,
bytes memory data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId);
}
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId);
}
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
function _requireMinted(uint256 tokenId) internal view virtual {
require(_exists(tokenId), "ERC721: invalid token ID");
}
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
文件 6 的 23:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 7 的 23:IERC20.sol
pragma solidity ^0.8.0;
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);
}
文件 8 的 23:IERC2981.sol
pragma solidity ^0.8.0;
import "../utils/introspection/IERC165.sol";
interface IERC2981 is IERC165 {
function royaltyInfo(uint256 tokenId, uint256 salePrice)
external
view
returns (address receiver, uint256 royaltyAmount);
}
文件 9 的 23: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,
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);
}
文件 10 的 23:IERC721Metadata.sol
pragma solidity ^0.8.0;
import "../IERC721.sol";
interface IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
文件 11 的 23:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 12 的 23:IWasabiConduit.sol
pragma solidity 0.8.19;
import "./lib/WasabiStructs.sol";
import "./WasabiOption.sol";
interface IWasabiConduit {
function buyOptions(
WasabiStructs.PoolAsk[] calldata _requests,
WasabiStructs.Ask[] calldata _asks,
bytes[] calldata _signatures
) external payable returns (uint256[] memory);
function buyOption(
WasabiStructs.PoolAsk calldata _request,
bytes calldata _signature
) external payable returns (uint256);
function transferToken(
address _nft,
uint256 _tokenId,
address _target
) external;
function setOption(WasabiOption _option) external;
function setMaxOptionsToBuy(uint256 _maxOptionsToBuy) external;
function setPoolFactoryAddress(address _factory) external;
function acceptAsk(
WasabiStructs.Ask calldata _ask,
bytes calldata _signature
) external payable returns (uint256);
function acceptBid(
uint256 _optionId,
address _poolAddress,
WasabiStructs.Bid calldata _bid,
bytes calldata _signature
) external payable;
function poolAcceptBid(WasabiStructs.Bid calldata _bid, bytes calldata _signature, uint256 _optionId) external;
function cancelAsk(
WasabiStructs.Ask calldata _ask,
bytes calldata _signature
) external;
function cancelBid(
WasabiStructs.Bid calldata _bid,
bytes calldata _signature
) external;
}
文件 13 的 23:IWasabiErrors.sol
pragma solidity 0.8.19;
interface IWasabiErrors {
error OrderFilledOrCancelled();
error Unauthorized();
error InvalidSignature();
error InsufficientAvailableLiquidity();
error RequestNftIsLocked();
error NftIsInvalid();
error InvalidExpiry();
error InvalidStrike();
error HasExpired();
error FailedToSend();
}
文件 14 的 23:IWasabiFeeManager.sol
pragma solidity 0.8.19;
import "@openzeppelin/contracts/access/Ownable.sol";
interface IWasabiFeeManager {
function getFeeData(address _pool, uint256 _amount) external view returns (address receiver, uint256 amount);
function getFeeDataForOption(uint256 _optionId, uint256 _amount) external view returns (address receiver, uint256 amount);
}
文件 15 的 23:IWasabiPool.sol
pragma solidity 0.8.19;
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "./lib/WasabiStructs.sol";
interface IWasabiPool is IERC165, IERC721Receiver {
event AdminChanged(address admin);
event OrderCancelled(uint256 id);
event PoolBidTaken(uint256 id);
event ERC721Received(uint256 tokenId);
event ETHReceived(uint amount);
event ERC20Received(uint amount);
event ERC721Withdrawn(uint256 tokenId);
event ERC20Withdrawn(uint amount);
event ETHWithdrawn(uint amount);
event OptionExecuted(uint256 optionId);
event OptionIssued(uint256 optionId, uint256 price);
event OptionIssued(uint256 optionId, uint256 price, uint256 poolAskId);
event PoolSettingsChanged();
function getNftAddress() external view returns(address);
function getLiquidityAddress() external view returns(address);
function writeOption(
WasabiStructs.PoolAsk calldata _request, bytes calldata _signature
) external payable returns (uint256);
function writeOptionTo(
WasabiStructs.PoolAsk calldata _request, bytes calldata _signature, address _receiver
) external payable returns (uint256);
function executeOption(uint256 _optionId) external payable;
function executeOptionWithSell(uint256 _optionId, uint256 _tokenId) external payable;
function cancelOrder(uint256 _orderId) external;
function withdrawERC721(IERC721 _nft, uint256[] calldata _tokenIds) external;
function depositERC721(IERC721 _nft, uint256[] calldata _tokenIds) external;
function withdrawETH(uint256 _amount) external payable;
function withdrawERC20(IERC20 _token, uint256 _amount) external;
function setAdmin(address _admin) external;
function removeAdmin() external;
function getAdmin() external view returns (address);
function getFactory() external view returns (address);
function availableBalance() view external returns(uint256);
function getOptionIds() external view returns(uint256[] memory);
function getOptionIdForToken(uint256 _tokenId) external view returns(uint256);
function getOptionData(uint256 _optionId) external view returns(WasabiStructs.OptionData memory);
function isValid(uint256 _optionId) view external returns(bool);
function isAvailableTokenId(uint256 _tokenId) external view returns(bool);
function clearExpiredOptions(uint256[] memory _optionIds) external;
function acceptBid(WasabiStructs.Bid calldata _bid, bytes calldata _signature, uint256 _tokenId) external returns(uint256);
function acceptAsk(WasabiStructs.Ask calldata _ask, bytes calldata _signature) external;
function acceptPoolBid(WasabiStructs.PoolBid calldata _poolBid, bytes calldata _signature) external payable;
}
文件 16 的 23:IWasabiPoolFactory.sol
pragma solidity 0.8.19;
interface IWasabiPoolFactory {
enum PoolState {
INVALID,
ACTIVE,
DISABLED
}
event NewPool(address poolAddress, address indexed nftAddress, address indexed owner);
function togglePool(address _poolAddress, PoolState _poolState) external;
function isValidPool(address _poolAddress) external view returns(bool);
function getPoolState(address _poolAddress) external view returns(PoolState);
function getConduitAddress() external view returns(address);
function getFeeManager() external view returns(address);
}
文件 17 的 23: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());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
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);
}
}
文件 18 的 23: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;
}
}
文件 19 的 23:Signing.sol
pragma solidity 0.8.19;
import {WasabiStructs} from "./WasabiStructs.sol";
library Signing {
function getMessageHash(WasabiStructs.PoolAsk calldata _request) public pure returns (bytes32) {
return keccak256(
abi.encode(
_request.id,
_request.poolAddress,
_request.optionType,
_request.strikePrice,
_request.premium,
_request.expiry,
_request.tokenId,
_request.orderExpiry));
}
function getAskHash(WasabiStructs.Ask calldata _ask) public pure returns (bytes32) {
return keccak256(
abi.encode(
_ask.id,
_ask.price,
_ask.tokenAddress,
_ask.orderExpiry,
_ask.seller,
_ask.optionId));
}
function getBidHash(WasabiStructs.Bid calldata _bid) public pure returns (bytes32) {
return keccak256(
abi.encode(
_bid.id,
_bid.price,
_bid.tokenAddress,
_bid.collection,
_bid.orderExpiry,
_bid.buyer,
_bid.optionType,
_bid.strikePrice,
_bid.expiry,
_bid.expiryAllowance));
}
function getEthSignedMessageHash(bytes32 _messageHash) public pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash));
}
function getSigner(
WasabiStructs.PoolAsk calldata _request,
bytes memory signature
) public pure returns (address) {
bytes32 messageHash = getMessageHash(_request);
bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);
return recoverSigner(ethSignedMessageHash, signature);
}
function getAskSigner(
WasabiStructs.Ask calldata _ask,
bytes memory signature
) public pure returns (address) {
bytes32 messageHash = getAskHash(_ask);
bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);
return recoverSigner(ethSignedMessageHash, signature);
}
function recoverSigner(bytes32 _ethSignedMessageHash, bytes memory _signature)
public
pure
returns (address)
{
(bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);
return ecrecover(_ethSignedMessageHash, v, r, s);
}
function splitSignature(bytes memory sig)
public
pure
returns (
bytes32 r,
bytes32 s,
uint8 v
)
{
require(sig.length == 65, "invalid signature length");
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := byte(0, mload(add(sig, 96)))
}
}
}
文件 20 的 23:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
文件 21 的 23:WasabiConduit.sol
pragma solidity 0.8.19;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../IWasabiPool.sol";
import "../IWasabiErrors.sol";
import "../IWasabiPoolFactory.sol";
import "../IWasabiConduit.sol";
import "../WasabiOption.sol";
import "./ConduitSignatureVerifier.sol";
import "../fees/IWasabiFeeManager.sol";
contract WasabiConduit is
Ownable,
IERC721Receiver,
ReentrancyGuard,
ConduitSignatureVerifier,
IWasabiConduit
{
event AskTaken(
uint256 optionId,
uint256 orderId,
address seller,
address taker
);
event BidTaken(
uint256 optionId,
uint256 orderId,
address buyer,
address taker
);
event BidCancelled(uint256 orderId, address buyer);
event AskCancelled(uint256 orderId, address seller);
WasabiOption private option;
uint256 public maxOptionsToBuy;
mapping(bytes => bool) public idToFinalizedOrCancelled;
address private factory;
constructor(WasabiOption _option) {
option = _option;
maxOptionsToBuy = 100;
}
function buyOptions(
WasabiStructs.PoolAsk[] calldata _requests,
WasabiStructs.Ask[] calldata _asks,
bytes[] calldata _signatures
) external payable returns (uint256[] memory) {
uint256 size = _requests.length + _asks.length;
require(size > 0, "Need to provide at least one request");
require(size <= maxOptionsToBuy, "Cannot buy that many options");
require(
size == _signatures.length,
"Need to provide the same amount of signatures and requests"
);
uint256[] memory optionIds = new uint[](size);
for (uint256 index = 0; index < _requests.length; index++) {
uint256 tokenId = buyOption(_requests[index], _signatures[index]);
optionIds[index] = tokenId;
}
for (uint256 index = 0; index < _asks.length; index++) {
uint256 sigIndex = index + _requests.length;
uint256 tokenId = acceptAsk(
_asks[index],
_signatures[sigIndex]
);
optionIds[sigIndex] = tokenId;
}
return optionIds;
}
function buyOption(
WasabiStructs.PoolAsk calldata _request,
bytes calldata _signature
) public payable returns (uint256) {
IWasabiPoolFactory poolFactory = IWasabiPoolFactory(factory);
IWasabiFeeManager feeManager = IWasabiFeeManager(poolFactory.getFeeManager());
(, uint256 feeAmount) = feeManager.getFeeData(_request.poolAddress, _request.premium);
uint256 amount = _request.premium + feeAmount;
IWasabiPool pool = IWasabiPool(_request.poolAddress);
if (pool.getLiquidityAddress() != address(0)) {
IERC20 erc20 = IERC20(pool.getLiquidityAddress());
if (!erc20.transferFrom(_msgSender(), address(this), amount)) {
revert IWasabiErrors.FailedToSend();
}
erc20.approve(_request.poolAddress, amount);
return pool.writeOptionTo(_request, _signature, _msgSender());
} else {
require(msg.value >= amount, "Not enough ETH supplied");
return pool.writeOptionTo{value: amount}(_request, _signature, _msgSender());
}
}
function onERC721Received(
address ,
address ,
uint256 ,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
function transferToken(
address _nft,
uint256 _tokenId,
address _target
) external onlyOwner {
IERC721(_nft).safeTransferFrom(address(this), _target, _tokenId);
}
function setOption(WasabiOption _option) external onlyOwner {
option = _option;
}
function setMaxOptionsToBuy(uint256 _maxOptionsToBuy) external onlyOwner {
maxOptionsToBuy = _maxOptionsToBuy;
}
function setPoolFactoryAddress(address _factory) external onlyOwner {
factory = _factory;
}
function acceptAsk(
WasabiStructs.Ask calldata _ask,
bytes calldata _signature
) public payable nonReentrant returns (uint256) {
bytes memory id = getAskId(_ask);
require(
!idToFinalizedOrCancelled[id],
"Order was finalized or cancelled"
);
validateAsk(_ask, _signature);
uint256 price = _ask.price;
(address royaltyAddress, uint256 royaltyAmount) = option.royaltyInfo(
_ask.optionId,
price
);
if (_ask.tokenAddress == address(0)) {
require(msg.value >= price, "Not enough ETH supplied");
if (royaltyAmount > 0) {
(bool sent, ) = payable(royaltyAddress).call{value: royaltyAmount}("");
if (!sent) {
revert IWasabiErrors.FailedToSend();
}
price -= royaltyAmount;
}
(bool _sent, ) = payable(_ask.seller).call{value: price}("");
if (!_sent) {
revert IWasabiErrors.FailedToSend();
}
} else {
IERC20 erc20 = IERC20(_ask.tokenAddress);
if (royaltyAmount > 0) {
if(!erc20.transferFrom(_msgSender(), royaltyAddress, royaltyAmount)) {
revert IWasabiErrors.FailedToSend();
}
price -= royaltyAmount;
}
if (!erc20.transferFrom(_msgSender(), _ask.seller, price)) {
revert IWasabiErrors.FailedToSend();
}
}
option.safeTransferFrom(_ask.seller, _msgSender(), _ask.optionId);
idToFinalizedOrCancelled[id] = true;
emit AskTaken(_ask.optionId, _ask.id, _ask.seller, _msgSender());
return _ask.optionId;
}
function acceptBid(
uint256 _optionId,
address _poolAddress,
WasabiStructs.Bid calldata _bid,
bytes calldata _signature
) external payable nonReentrant {
bytes memory id = getBidId(_bid);
require(
!idToFinalizedOrCancelled[id],
"Order was finalized or cancelled"
);
IWasabiPool pool = IWasabiPool(_poolAddress);
validateOptionForBid(_optionId, pool, _bid);
validateBid(pool, _bid, _signature);
uint256 price = _bid.price;
(address royaltyAddress, uint256 royaltyAmount) = option.royaltyInfo(
_optionId,
price
);
IERC20 erc20 = IERC20(_bid.tokenAddress);
if (royaltyAmount > 0) {
if (!erc20.transferFrom(_bid.buyer, royaltyAddress, royaltyAmount)) {
revert IWasabiErrors.FailedToSend();
}
price -= royaltyAmount;
}
if (!erc20.transferFrom(_bid.buyer, _msgSender(), price)) {
revert IWasabiErrors.FailedToSend();
}
option.safeTransferFrom(_msgSender(), _bid.buyer, _optionId);
idToFinalizedOrCancelled[id] = true;
emit BidTaken(_optionId, _bid.id, _bid.buyer, _msgSender());
}
function poolAcceptBid(WasabiStructs.Bid calldata _bid, bytes calldata _signature, uint256 _optionId) external {
bytes memory id = getBidId(_bid);
address poolAddress = _msgSender();
require(
!idToFinalizedOrCancelled[id],
"Order was finalized or cancelled"
);
require(IWasabiPoolFactory(factory).isValidPool(_msgSender()), "Pool is not valid");
IWasabiPool pool = IWasabiPool(poolAddress);
validateBid(pool, _bid, _signature);
IERC20 erc20 = IERC20(_bid.tokenAddress);
(address royaltyAddress, uint256 royaltyAmount) = option.royaltyInfo(_optionId, _bid.price);
if (royaltyAmount > 0) {
if (!erc20.transferFrom(_bid.buyer, royaltyAddress, royaltyAmount)) {
revert IWasabiErrors.FailedToSend();
}
}
if (!erc20.transferFrom(_bid.buyer, poolAddress, _bid.price - royaltyAmount)) {
revert IWasabiErrors.FailedToSend();
}
idToFinalizedOrCancelled[id] = true;
emit BidTaken(_optionId, _bid.id, _bid.buyer, poolAddress);
}
function validateAsk(
WasabiStructs.Ask calldata _ask,
bytes calldata _signature
) internal view {
address currentOwner = option.ownerOf(_ask.optionId);
require(
verifyAsk(_ask, _signature, owner()) || verifyAsk(_ask, _signature, currentOwner),
"Incorrect signature"
);
require(currentOwner == _ask.seller, "Seller is not owner");
require(_ask.orderExpiry >= block.timestamp, "Order expired");
require(_ask.price > 0, "Price needs to be greater than 0");
}
function validateOptionForBid(
uint256 _optionId,
IWasabiPool _pool,
WasabiStructs.Bid calldata _bid
) internal view {
require(
option.ownerOf(_optionId) == _msgSender(),
"Seller is not owner"
);
WasabiStructs.OptionData memory optionData = _pool.getOptionData(_optionId);
require(
optionData.optionType == _bid.optionType,
"Option types don't match"
);
require(
optionData.strikePrice == _bid.strikePrice,
"Strike prices don't match"
);
uint256 diff = optionData.expiry > _bid.expiry
? optionData.expiry - _bid.expiry
: _bid.expiry - optionData.expiry;
require(diff <= _bid.expiryAllowance, "Not within expiry range");
}
function validateBid(
IWasabiPool _pool,
WasabiStructs.Bid calldata _bid,
bytes calldata _signature
) internal view {
require(
verifyBid(_bid, _signature, owner()) ||
verifyBid(_bid, _signature, _bid.buyer),
"Incorrect signature"
);
require(
_bid.tokenAddress != address(0),
"Bidder didn't provide a ERC20 token"
);
require(_bid.orderExpiry >= block.timestamp, "Order expired");
require(_bid.price > 0, "Price needs to be greater than 0");
require(_pool.getNftAddress() == _bid.collection, "Collections don't match");
require(_pool.getLiquidityAddress() == _bid.optionTokenAddress, "Option liquidity doesn't match");
}
function cancelAsk(
WasabiStructs.Ask calldata _ask,
bytes calldata _signature
) external {
require(verifyAsk(_ask, _signature, _ask.seller), "Incorrect signature");
require(_msgSender() == _ask.seller, "Only the signer can cancel");
bytes memory id = getAskId(_ask);
require(
!idToFinalizedOrCancelled[id],
"Order was already finalized or cancelled"
);
idToFinalizedOrCancelled[id] = true;
emit AskCancelled(_ask.id, _ask.seller);
}
function cancelBid(
WasabiStructs.Bid calldata _bid,
bytes calldata _signature
) external {
require(verifyBid(_bid, _signature, _bid.buyer), "Incorrect signature");
require(_msgSender() == _bid.buyer, "Only the signer can cancel");
bytes memory id = getBidId(_bid);
require(
!idToFinalizedOrCancelled[id],
"Order was already finalized or cancelled"
);
idToFinalizedOrCancelled[id] = true;
emit BidCancelled(_bid.id, _bid.buyer);
}
function getAskId(
WasabiStructs.Ask calldata _ask
) internal pure returns (bytes memory) {
return abi.encodePacked(_ask.seller, _ask.id);
}
function getBidId(
WasabiStructs.Bid calldata _bid
) internal pure returns (bytes memory) {
return abi.encodePacked(_bid.buyer, _bid.id);
}
}
文件 22 的 23:WasabiOption.sol
pragma solidity 0.8.19;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/interfaces/IERC2981.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "./IWasabiPool.sol";
import "./IWasabiPoolFactory.sol";
import "./fees/IWasabiFeeManager.sol";
contract WasabiOption is ERC721, IERC2981, Ownable {
address private lastFactory;
mapping(address => bool) private factoryAddresses;
mapping(uint256 => address) private optionPools;
uint256 private _currentId = 1;
string private _baseURIextended;
constructor() ERC721("Wasabi Option NFTs", "WASAB") {}
function toggleFactory(address _factory, bool _enabled) external onlyOwner {
factoryAddresses[_factory] = _enabled;
if (_enabled) {
lastFactory = _factory;
}
}
function mint(address _to, address _factory) external returns (uint256 mintedId) {
require(factoryAddresses[_factory] == true, "Invalid Factory");
require(IWasabiPoolFactory(_factory).isValidPool(_msgSender()), "Only valid pools can mint");
_safeMint(_to, _currentId);
mintedId = _currentId;
optionPools[mintedId] = _msgSender();
_currentId++;
}
function burn(uint256 _optionId) external {
require(optionPools[_optionId] == _msgSender(), "Caller can't burn option");
_burn(_optionId);
}
function setBaseURI(string memory baseURI_) external onlyOwner {
_baseURIextended = baseURI_;
}
function getPool(uint256 _optionId) external view returns (address) {
return optionPools[_optionId];
}
function _baseURI() internal view virtual override returns (string memory) {
return _baseURIextended;
}
function royaltyInfo(uint256 _tokenId, uint256 _salePrice) external view returns (address, uint256) {
IWasabiPool pool = IWasabiPool(optionPools[_tokenId]);
IWasabiPoolFactory factory = IWasabiPoolFactory(pool.getFactory());
IWasabiFeeManager feeManager = IWasabiFeeManager(factory.getFeeManager());
return feeManager.getFeeDataForOption(_tokenId, _salePrice);
}
function supportsInterface(bytes4 interfaceId) public view override(ERC721, IERC165) returns (bool) {
return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
}
}
文件 23 的 23:WasabiStructs.sol
pragma solidity 0.8.19;
library WasabiStructs {
enum OptionType {
CALL,
PUT
}
struct OptionData {
bool active;
OptionType optionType;
uint256 strikePrice;
uint256 expiry;
uint256 tokenId;
}
struct PoolAsk {
uint256 id;
address poolAddress;
OptionType optionType;
uint256 strikePrice;
uint256 premium;
uint256 expiry;
uint256 tokenId;
uint256 orderExpiry;
}
struct PoolBid {
uint256 id;
uint256 price;
address tokenAddress;
uint256 orderExpiry;
uint256 optionId;
}
struct Bid {
uint256 id;
uint256 price;
address tokenAddress;
address collection;
uint256 orderExpiry;
address buyer;
OptionType optionType;
uint256 strikePrice;
uint256 expiry;
uint256 expiryAllowance;
address optionTokenAddress;
}
struct Ask {
uint256 id;
uint256 price;
address tokenAddress;
uint256 orderExpiry;
address seller;
uint256 optionId;
}
struct EIP712Domain {
string name;
string version;
uint256 chainId;
address verifyingContract;
}
}
{
"compilationTarget": {
"project:/contracts/conduit/WasabiConduit.sol": "WasabiConduit"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1500
},
"remappings": []
}
[{"inputs":[{"internalType":"contract WasabiOption","name":"_option","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FailedToSend","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":false,"internalType":"address","name":"seller","type":"address"}],"name":"AskCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"optionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":false,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"address","name":"taker","type":"address"}],"name":"AskTaken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"}],"name":"BidCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"optionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"address","name":"taker","type":"address"}],"name":"BidTaken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"uint256","name":"optionId","type":"uint256"}],"internalType":"struct WasabiStructs.Ask","name":"_ask","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"acceptAsk","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_optionId","type":"uint256"},{"internalType":"address","name":"_poolAddress","type":"address"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"},{"internalType":"address","name":"buyer","type":"address"},{"internalType":"enum WasabiStructs.OptionType","name":"optionType","type":"uint8"},{"internalType":"uint256","name":"strikePrice","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"expiryAllowance","type":"uint256"},{"internalType":"address","name":"optionTokenAddress","type":"address"}],"internalType":"struct WasabiStructs.Bid","name":"_bid","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"acceptBid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"enum WasabiStructs.OptionType","name":"optionType","type":"uint8"},{"internalType":"uint256","name":"strikePrice","type":"uint256"},{"internalType":"uint256","name":"premium","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"}],"internalType":"struct WasabiStructs.PoolAsk","name":"_request","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"buyOption","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"enum WasabiStructs.OptionType","name":"optionType","type":"uint8"},{"internalType":"uint256","name":"strikePrice","type":"uint256"},{"internalType":"uint256","name":"premium","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"}],"internalType":"struct WasabiStructs.PoolAsk[]","name":"_requests","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"uint256","name":"optionId","type":"uint256"}],"internalType":"struct WasabiStructs.Ask[]","name":"_asks","type":"tuple[]"},{"internalType":"bytes[]","name":"_signatures","type":"bytes[]"}],"name":"buyOptions","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"uint256","name":"optionId","type":"uint256"}],"internalType":"struct WasabiStructs.Ask","name":"_ask","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"cancelAsk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"},{"internalType":"address","name":"buyer","type":"address"},{"internalType":"enum WasabiStructs.OptionType","name":"optionType","type":"uint8"},{"internalType":"uint256","name":"strikePrice","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"expiryAllowance","type":"uint256"},{"internalType":"address","name":"optionTokenAddress","type":"address"}],"internalType":"struct WasabiStructs.Bid","name":"_bid","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"cancelBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"uint256","name":"optionId","type":"uint256"}],"internalType":"struct WasabiStructs.Ask","name":"_ask","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"getSignerForAsk","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"},{"internalType":"address","name":"buyer","type":"address"},{"internalType":"enum WasabiStructs.OptionType","name":"optionType","type":"uint8"},{"internalType":"uint256","name":"strikePrice","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"expiryAllowance","type":"uint256"},{"internalType":"address","name":"optionTokenAddress","type":"address"}],"internalType":"struct WasabiStructs.Bid","name":"_bid","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"getSignerForBid","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"uint256","name":"optionId","type":"uint256"}],"internalType":"struct WasabiStructs.Ask","name":"_ask","type":"tuple"}],"name":"hashForAsk","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"},{"internalType":"address","name":"buyer","type":"address"},{"internalType":"enum WasabiStructs.OptionType","name":"optionType","type":"uint8"},{"internalType":"uint256","name":"strikePrice","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"expiryAllowance","type":"uint256"},{"internalType":"address","name":"optionTokenAddress","type":"address"}],"internalType":"struct WasabiStructs.Bid","name":"_bid","type":"tuple"}],"name":"hashForBid","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"idToFinalizedOrCancelled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxOptionsToBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","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":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"orderExpiry","type":"uint256"},{"internalType":"address","name":"buyer","type":"address"},{"internalType":"enum WasabiStructs.OptionType","name":"optionType","type":"uint8"},{"internalType":"uint256","name":"strikePrice","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"expiryAllowance","type":"uint256"},{"internalType":"address","name":"optionTokenAddress","type":"address"}],"internalType":"struct WasabiStructs.Bid","name":"_bid","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"uint256","name":"_optionId","type":"uint256"}],"name":"poolAcceptBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxOptionsToBuy","type":"uint256"}],"name":"setMaxOptionsToBuy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract WasabiOption","name":"_option","type":"address"}],"name":"setOption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_factory","type":"address"}],"name":"setPoolFactoryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nft","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_target","type":"address"}],"name":"transferToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]