文件 1 的 14:Address.sol
pragma solidity >=0.6.2 <0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 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 _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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 的 14:AuctionHouse.sol
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2;
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
import { IERC721, IERC165 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import {Counters} from "@openzeppelin/contracts/utils/Counters.sol";
import { IMarket, Decimal } from "@zoralabs/core/dist/contracts/interfaces/IMarket.sol";
import { IMedia } from "@zoralabs/core/dist/contracts/interfaces/IMedia.sol";
import { IAuctionHouse } from "./interfaces/IAuctionHouse.sol";
interface IWETH {
function deposit() external payable;
function withdraw(uint wad) external;
function transfer(address to, uint256 value) external returns (bool);
}
interface IMediaExtended is IMedia {
function marketContract() external returns(address);
}
contract AuctionHouse is IAuctionHouse, ReentrancyGuard {
using SafeMath for uint256;
using SafeERC20 for IERC20;
using Counters for Counters.Counter;
uint256 public timeBuffer;
uint8 public minBidIncrementPercentage;
address public zora;
address public wethAddress;
mapping(uint256 => IAuctionHouse.Auction) public auctions;
bytes4 constant interfaceId = 0x80ac58cd;
Counters.Counter private _auctionIdTracker;
modifier auctionExists(uint256 auctionId) {
require(_exists(auctionId), "Auction doesn't exist");
_;
}
constructor(address _zora, address _weth) public {
require(
IERC165(_zora).supportsInterface(interfaceId),
"Doesn't support NFT interface"
);
zora = _zora;
wethAddress = _weth;
timeBuffer = 15 * 60;
minBidIncrementPercentage = 5;
}
function createAuction(
uint256 tokenId,
address tokenContract,
uint256 duration,
uint256 reservePrice,
address payable curator,
uint8 curatorFeePercentage,
address auctionCurrency
) public override nonReentrant returns (uint256) {
require(
IERC165(tokenContract).supportsInterface(interfaceId),
"tokenContract does not support ERC721 interface"
);
require(curatorFeePercentage < 100, "curatorFeePercentage must be less than 100");
address tokenOwner = IERC721(tokenContract).ownerOf(tokenId);
require(msg.sender == IERC721(tokenContract).getApproved(tokenId) || msg.sender == tokenOwner, "Caller must be approved or owner for token id");
uint256 auctionId = _auctionIdTracker.current();
auctions[auctionId] = Auction({
tokenId: tokenId,
tokenContract: tokenContract,
approved: false,
amount: 0,
duration: duration,
firstBidTime: 0,
reservePrice: reservePrice,
curatorFeePercentage: curatorFeePercentage,
tokenOwner: tokenOwner,
bidder: address(0),
curator: curator,
auctionCurrency: auctionCurrency
});
IERC721(tokenContract).transferFrom(tokenOwner, address(this), tokenId);
_auctionIdTracker.increment();
emit AuctionCreated(auctionId, tokenId, tokenContract, duration, reservePrice, tokenOwner, curator, curatorFeePercentage, auctionCurrency);
if(auctions[auctionId].curator == address(0) || curator == tokenOwner) {
_approveAuction(auctionId, true);
}
return auctionId;
}
function setAuctionApproval(uint256 auctionId, bool approved) external override auctionExists(auctionId) {
require(msg.sender == auctions[auctionId].curator, "Must be auction curator");
require(auctions[auctionId].firstBidTime == 0, "Auction has already started");
_approveAuction(auctionId, approved);
}
function setAuctionReservePrice(uint256 auctionId, uint256 reservePrice) external override auctionExists(auctionId) {
require(msg.sender == auctions[auctionId].curator || msg.sender == auctions[auctionId].tokenOwner, "Must be auction curator or token owner");
require(auctions[auctionId].firstBidTime == 0, "Auction has already started");
auctions[auctionId].reservePrice = reservePrice;
emit AuctionReservePriceUpdated(auctionId, auctions[auctionId].tokenId, auctions[auctionId].tokenContract, reservePrice);
}
function createBid(uint256 auctionId, uint256 amount)
external
override
payable
auctionExists(auctionId)
nonReentrant
{
address payable lastBidder = auctions[auctionId].bidder;
require(auctions[auctionId].approved, "Auction must be approved by curator");
require(
auctions[auctionId].firstBidTime == 0 ||
block.timestamp <
auctions[auctionId].firstBidTime.add(auctions[auctionId].duration),
"Auction expired"
);
require(
amount >= auctions[auctionId].reservePrice,
"Must send at least reservePrice"
);
require(
amount >= auctions[auctionId].amount.add(
auctions[auctionId].amount.mul(minBidIncrementPercentage).div(100)
),
"Must send more than last bid by minBidIncrementPercentage amount"
);
if(auctions[auctionId].tokenContract == zora) {
require(
IMarket(IMediaExtended(zora).marketContract()).isValidBid(
auctions[auctionId].tokenId,
amount
),
"Bid invalid for share splitting"
);
}
if(auctions[auctionId].firstBidTime == 0) {
auctions[auctionId].firstBidTime = block.timestamp;
} else if(lastBidder != address(0)) {
_handleOutgoingBid(lastBidder, auctions[auctionId].amount, auctions[auctionId].auctionCurrency);
}
_handleIncomingBid(amount, auctions[auctionId].auctionCurrency);
auctions[auctionId].amount = amount;
auctions[auctionId].bidder = msg.sender;
bool extended = false;
if (
auctions[auctionId].firstBidTime.add(auctions[auctionId].duration).sub(
block.timestamp
) < timeBuffer
) {
uint256 oldDuration = auctions[auctionId].duration;
auctions[auctionId].duration =
oldDuration.add(timeBuffer.sub(auctions[auctionId].firstBidTime.add(oldDuration).sub(block.timestamp)));
extended = true;
}
emit AuctionBid(
auctionId,
auctions[auctionId].tokenId,
auctions[auctionId].tokenContract,
msg.sender,
amount,
lastBidder == address(0),
extended
);
if (extended) {
emit AuctionDurationExtended(
auctionId,
auctions[auctionId].tokenId,
auctions[auctionId].tokenContract,
auctions[auctionId].duration
);
}
}
function endAuction(uint256 auctionId) external override auctionExists(auctionId) nonReentrant {
require(
uint256(auctions[auctionId].firstBidTime) != 0,
"Auction hasn't begun"
);
require(
block.timestamp >=
auctions[auctionId].firstBidTime.add(auctions[auctionId].duration),
"Auction hasn't completed"
);
address currency = auctions[auctionId].auctionCurrency == address(0) ? wethAddress : auctions[auctionId].auctionCurrency;
uint256 curatorFee = 0;
uint256 tokenOwnerProfit = auctions[auctionId].amount;
if(auctions[auctionId].tokenContract == zora) {
(bool success, uint256 remainingProfit) = _handleZoraAuctionSettlement(auctionId);
tokenOwnerProfit = remainingProfit;
if(success != true) {
_handleOutgoingBid(auctions[auctionId].bidder, auctions[auctionId].amount, auctions[auctionId].auctionCurrency);
_cancelAuction(auctionId);
return;
}
} else {
try IERC721(auctions[auctionId].tokenContract).safeTransferFrom(address(this), auctions[auctionId].bidder, auctions[auctionId].tokenId) {} catch {
_handleOutgoingBid(auctions[auctionId].bidder, auctions[auctionId].amount, auctions[auctionId].auctionCurrency);
_cancelAuction(auctionId);
return;
}
}
if(auctions[auctionId].curator != address(0)) {
curatorFee = tokenOwnerProfit.mul(auctions[auctionId].curatorFeePercentage).div(100);
tokenOwnerProfit = tokenOwnerProfit.sub(curatorFee);
_handleOutgoingBid(auctions[auctionId].curator, curatorFee, auctions[auctionId].auctionCurrency);
}
_handleOutgoingBid(auctions[auctionId].tokenOwner, tokenOwnerProfit, auctions[auctionId].auctionCurrency);
emit AuctionEnded(
auctionId,
auctions[auctionId].tokenId,
auctions[auctionId].tokenContract,
auctions[auctionId].tokenOwner,
auctions[auctionId].curator,
auctions[auctionId].bidder,
tokenOwnerProfit,
curatorFee,
currency
);
delete auctions[auctionId];
}
function cancelAuction(uint256 auctionId) external override nonReentrant auctionExists(auctionId) {
require(
auctions[auctionId].tokenOwner == msg.sender || auctions[auctionId].curator == msg.sender,
"Can only be called by auction creator or curator"
);
require(
uint256(auctions[auctionId].firstBidTime) == 0,
"Can't cancel an auction once it's begun"
);
_cancelAuction(auctionId);
}
function _handleIncomingBid(uint256 amount, address currency) internal {
if(currency == address(0)) {
require(msg.value == amount, "Sent ETH Value does not match specified bid amount");
IWETH(wethAddress).deposit{value: amount}();
} else {
IERC20 token = IERC20(currency);
uint256 beforeBalance = token.balanceOf(address(this));
token.safeTransferFrom(msg.sender, address(this), amount);
uint256 afterBalance = token.balanceOf(address(this));
require(beforeBalance.add(amount) == afterBalance, "Token transfer call did not transfer expected amount");
}
}
function _handleOutgoingBid(address to, uint256 amount, address currency) internal {
if(currency == address(0)) {
IWETH(wethAddress).withdraw(amount);
if(!_safeTransferETH(to, amount)) {
IWETH(wethAddress).deposit{value: amount}();
IERC20(wethAddress).safeTransfer(to, amount);
}
} else {
IERC20(currency).safeTransfer(to, amount);
}
}
function _safeTransferETH(address to, uint256 value) internal returns (bool) {
(bool success, ) = to.call{value: value}(new bytes(0));
return success;
}
function _cancelAuction(uint256 auctionId) internal {
address tokenOwner = auctions[auctionId].tokenOwner;
IERC721(auctions[auctionId].tokenContract).safeTransferFrom(address(this), tokenOwner, auctions[auctionId].tokenId);
emit AuctionCanceled(auctionId, auctions[auctionId].tokenId, auctions[auctionId].tokenContract, tokenOwner);
delete auctions[auctionId];
}
function _approveAuction(uint256 auctionId, bool approved) internal {
auctions[auctionId].approved = approved;
emit AuctionApprovalUpdated(auctionId, auctions[auctionId].tokenId, auctions[auctionId].tokenContract, approved);
}
function _exists(uint256 auctionId) internal view returns(bool) {
return auctions[auctionId].tokenOwner != address(0);
}
function _handleZoraAuctionSettlement(uint256 auctionId) internal returns (bool, uint256) {
address currency = auctions[auctionId].auctionCurrency == address(0) ? wethAddress : auctions[auctionId].auctionCurrency;
IMarket.Bid memory bid = IMarket.Bid({
amount: auctions[auctionId].amount,
currency: currency,
bidder: address(this),
recipient: auctions[auctionId].bidder,
sellOnShare: Decimal.D256(0)
});
IERC20(currency).approve(IMediaExtended(zora).marketContract(), bid.amount);
IMedia(zora).setBid(auctions[auctionId].tokenId, bid);
uint256 beforeBalance = IERC20(currency).balanceOf(address(this));
try IMedia(zora).acceptBid(auctions[auctionId].tokenId, bid) {} catch {
IMediaExtended(zora).removeBid(auctions[auctionId].tokenId);
return (false, 0);
}
uint256 afterBalance = IERC20(currency).balanceOf(address(this));
return (true, afterBalance.sub(beforeBalance));
}
receive() external payable {}
fallback() external payable {}
}
文件 3 的 14:Counters.sol
pragma solidity >=0.6.0 <0.8.0;
import "../math/SafeMath.sol";
library Counters {
using SafeMath for uint256;
struct Counter {
uint256 _value;
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
counter._value += 1;
}
function decrement(Counter storage counter) internal {
counter._value = counter._value.sub(1);
}
}
文件 4 的 14:Decimal.sol
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2;
import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol";
import {Math} from "./Math.sol";
library Decimal {
using SafeMath for uint256;
uint256 constant BASE_POW = 18;
uint256 constant BASE = 10**BASE_POW;
struct D256 {
uint256 value;
}
function one() internal pure returns (D256 memory) {
return D256({value: BASE});
}
function onePlus(D256 memory d) internal pure returns (D256 memory) {
return D256({value: d.value.add(BASE)});
}
function mul(uint256 target, D256 memory d)
internal
pure
returns (uint256)
{
return Math.getPartial(target, d.value, BASE);
}
function div(uint256 target, D256 memory d)
internal
pure
returns (uint256)
{
return Math.getPartial(target, BASE, d.value);
}
}
文件 5 的 14:IAuctionHouse.sol
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2;
interface IAuctionHouse {
struct Auction {
uint256 tokenId;
address tokenContract;
bool approved;
uint256 amount;
uint256 duration;
uint256 firstBidTime;
uint256 reservePrice;
uint8 curatorFeePercentage;
address tokenOwner;
address payable bidder;
address payable curator;
address auctionCurrency;
}
event AuctionCreated(
uint256 indexed auctionId,
uint256 indexed tokenId,
address indexed tokenContract,
uint256 duration,
uint256 reservePrice,
address tokenOwner,
address curator,
uint8 curatorFeePercentage,
address auctionCurrency
);
event AuctionApprovalUpdated(
uint256 indexed auctionId,
uint256 indexed tokenId,
address indexed tokenContract,
bool approved
);
event AuctionReservePriceUpdated(
uint256 indexed auctionId,
uint256 indexed tokenId,
address indexed tokenContract,
uint256 reservePrice
);
event AuctionBid(
uint256 indexed auctionId,
uint256 indexed tokenId,
address indexed tokenContract,
address sender,
uint256 value,
bool firstBid,
bool extended
);
event AuctionDurationExtended(
uint256 indexed auctionId,
uint256 indexed tokenId,
address indexed tokenContract,
uint256 duration
);
event AuctionEnded(
uint256 indexed auctionId,
uint256 indexed tokenId,
address indexed tokenContract,
address tokenOwner,
address curator,
address winner,
uint256 amount,
uint256 curatorFee,
address auctionCurrency
);
event AuctionCanceled(
uint256 indexed auctionId,
uint256 indexed tokenId,
address indexed tokenContract,
address tokenOwner
);
function createAuction(
uint256 tokenId,
address tokenContract,
uint256 duration,
uint256 reservePrice,
address payable curator,
uint8 curatorFeePercentages,
address auctionCurrency
) external returns (uint256);
function setAuctionApproval(uint256 auctionId, bool approved) external;
function setAuctionReservePrice(uint256 auctionId, uint256 reservePrice) external;
function createBid(uint256 auctionId, uint256 amount) external payable;
function endAuction(uint256 auctionId) external;
function cancelAuction(uint256 auctionId) external;
}
文件 6 的 14:IERC165.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 7 的 14:IERC20.sol
pragma solidity >=0.6.0 <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);
}
文件 8 的 14:IERC721.sol
pragma solidity >=0.6.2 <0.8.0;
import "../../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;
}
文件 9 的 14:IMarket.sol
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2;
import {Decimal} from "../Decimal.sol";
interface IMarket {
struct Bid {
uint256 amount;
address currency;
address bidder;
address recipient;
Decimal.D256 sellOnShare;
}
struct Ask {
uint256 amount;
address currency;
}
struct BidShares {
Decimal.D256 prevOwner;
Decimal.D256 creator;
Decimal.D256 owner;
}
event BidCreated(uint256 indexed tokenId, Bid bid);
event BidRemoved(uint256 indexed tokenId, Bid bid);
event BidFinalized(uint256 indexed tokenId, Bid bid);
event AskCreated(uint256 indexed tokenId, Ask ask);
event AskRemoved(uint256 indexed tokenId, Ask ask);
event BidShareUpdated(uint256 indexed tokenId, BidShares bidShares);
function bidForTokenBidder(uint256 tokenId, address bidder)
external
view
returns (Bid memory);
function currentAskForToken(uint256 tokenId)
external
view
returns (Ask memory);
function bidSharesForToken(uint256 tokenId)
external
view
returns (BidShares memory);
function isValidBid(uint256 tokenId, uint256 bidAmount)
external
view
returns (bool);
function isValidBidShares(BidShares calldata bidShares)
external
pure
returns (bool);
function splitShare(Decimal.D256 calldata sharePercentage, uint256 amount)
external
pure
returns (uint256);
function configure(address mediaContractAddress) external;
function setBidShares(uint256 tokenId, BidShares calldata bidShares)
external;
function setAsk(uint256 tokenId, Ask calldata ask) external;
function removeAsk(uint256 tokenId) external;
function setBid(
uint256 tokenId,
Bid calldata bid,
address spender
) external;
function removeBid(uint256 tokenId, address bidder) external;
function acceptBid(uint256 tokenId, Bid calldata expectedBid) external;
}
文件 10 的 14:IMedia.sol
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2;
import {IMarket} from "./IMarket.sol";
interface IMedia {
struct EIP712Signature {
uint256 deadline;
uint8 v;
bytes32 r;
bytes32 s;
}
struct MediaData {
string tokenURI;
string metadataURI;
bytes32 contentHash;
bytes32 metadataHash;
}
event TokenURIUpdated(uint256 indexed _tokenId, address owner, string _uri);
event TokenMetadataURIUpdated(
uint256 indexed _tokenId,
address owner,
string _uri
);
function tokenMetadataURI(uint256 tokenId)
external
view
returns (string memory);
function mint(MediaData calldata data, IMarket.BidShares calldata bidShares)
external;
function mintWithSig(
address creator,
MediaData calldata data,
IMarket.BidShares calldata bidShares,
EIP712Signature calldata sig
) external;
function auctionTransfer(uint256 tokenId, address recipient) external;
function setAsk(uint256 tokenId, IMarket.Ask calldata ask) external;
function removeAsk(uint256 tokenId) external;
function setBid(uint256 tokenId, IMarket.Bid calldata bid) external;
function removeBid(uint256 tokenId) external;
function acceptBid(uint256 tokenId, IMarket.Bid calldata bid) external;
function revokeApproval(uint256 tokenId) external;
function updateTokenURI(uint256 tokenId, string calldata tokenURI) external;
function updateTokenMetadataURI(
uint256 tokenId,
string calldata metadataURI
) external;
function permit(
address spender,
uint256 tokenId,
EIP712Signature calldata sig
) external;
}
文件 11 的 14:Math.sol
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2;
import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol";
library Math {
using SafeMath for uint256;
function getPartial(
uint256 target,
uint256 numerator,
uint256 denominator
) internal pure returns (uint256) {
return target.mul(numerator).div(denominator);
}
function getPartialRoundUp(
uint256 target,
uint256 numerator,
uint256 denominator
) internal pure returns (uint256) {
if (target == 0 || numerator == 0) {
return SafeMath.div(0, denominator);
}
return target.mul(numerator).sub(1).div(denominator).add(1);
}
function to128(uint256 number) internal pure returns (uint128) {
uint128 result = uint128(number);
require(result == number, "Math: Unsafe cast to uint128");
return result;
}
function to96(uint256 number) internal pure returns (uint96) {
uint96 result = uint96(number);
require(result == number, "Math: Unsafe cast to uint96");
return result;
}
function to32(uint256 number) internal pure returns (uint32) {
uint32 result = uint32(number);
require(result == number, "Math: Unsafe cast to uint32");
return result;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
}
文件 12 的 14:ReentrancyGuard.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 13 的 14:SafeERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 14 的 14:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
{
"compilationTarget": {
"contracts/AuctionHouse.sol": "AuctionHouse"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_zora","type":"address"},{"internalType":"address","name":"_weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tokenContract","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"AuctionApprovalUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tokenContract","type":"address"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bool","name":"firstBid","type":"bool"},{"indexed":false,"internalType":"bool","name":"extended","type":"bool"}],"name":"AuctionBid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tokenContract","type":"address"},{"indexed":false,"internalType":"address","name":"tokenOwner","type":"address"}],"name":"AuctionCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tokenContract","type":"address"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reservePrice","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenOwner","type":"address"},{"indexed":false,"internalType":"address","name":"curator","type":"address"},{"indexed":false,"internalType":"uint8","name":"curatorFeePercentage","type":"uint8"},{"indexed":false,"internalType":"address","name":"auctionCurrency","type":"address"}],"name":"AuctionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tokenContract","type":"address"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"AuctionDurationExtended","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tokenContract","type":"address"},{"indexed":false,"internalType":"address","name":"tokenOwner","type":"address"},{"indexed":false,"internalType":"address","name":"curator","type":"address"},{"indexed":false,"internalType":"address","name":"winner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"curatorFee","type":"uint256"},{"indexed":false,"internalType":"address","name":"auctionCurrency","type":"address"}],"name":"AuctionEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tokenContract","type":"address"},{"indexed":false,"internalType":"uint256","name":"reservePrice","type":"uint256"}],"name":"AuctionReservePriceUpdated","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"auctions","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"bool","name":"approved","type":"bool"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"firstBidTime","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"},{"internalType":"uint8","name":"curatorFeePercentage","type":"uint8"},{"internalType":"address","name":"tokenOwner","type":"address"},{"internalType":"address payable","name":"bidder","type":"address"},{"internalType":"address payable","name":"curator","type":"address"},{"internalType":"address","name":"auctionCurrency","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"cancelAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"},{"internalType":"address payable","name":"curator","type":"address"},{"internalType":"uint8","name":"curatorFeePercentage","type":"uint8"},{"internalType":"address","name":"auctionCurrency","type":"address"}],"name":"createAuction","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"createBid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"endAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minBidIncrementPercentage","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setAuctionApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"}],"name":"setAuctionReservePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timeBuffer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wethAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"zora","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]