编译器
0.8.27+commit.40a35a09
文件 1 的 9:Auctions.sol
pragma solidity 0.8.27;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "solady/auth/Ownable.sol";
import "solady/utils/ReentrancyGuard.sol";
import "./IAuctions.sol";
import "./IBidTicket.sol";
enum Status {
Active,
Claimed,
Refunded,
Abandoned
}
struct Auction {
uint8 auctionType;
address tokenAddress;
uint64 endTime;
uint8 tokenCount;
Status status;
address highestBidder;
uint256 highestBid;
uint256 bidDelta;
uint256 bidderCount;
mapping(uint256 => address) bidders;
mapping(uint256 => uint256) tokenIds;
mapping(uint256 => uint256) amounts;
mapping(address => uint256) rewards;
}
contract Auctions is IAuctions, Ownable, ReentrancyGuard {
uint8 private constant AUCTION_TYPE_ERC721 = 0;
uint8 private constant AUCTION_TYPE_ERC1155 = 1;
IBidTicket public bidTicket;
address public theBarn;
address public theFarmer;
uint256 public abandonmentFeePercent = 20;
uint256 public antiSnipeDuration = 15 minutes;
uint256 public auctionDuration = 3 days;
uint256 public bidTicketCostBid = 1;
uint256 public bidTicketCostStart = 1;
uint256 public bidTicketTokenId = 1;
uint256 public maxTokens = 50;
uint256 public minBidIncrement = 0.01 ether;
uint256 public minStartingBid = 0.05 ether;
uint256 public nextAuctionId = 1;
uint256 public outbidRewardPercent = 10;
uint256 public settlementDuration = 7 days;
mapping(address => uint256) public balances;
mapping(uint256 => Auction) public auctions;
mapping(address => mapping(uint256 => bool)) public auctionTokensERC721;
mapping(address => mapping(uint256 => uint256)) public auctionTokensERC1155;
constructor(
address owner_,
address theBarn_,
address theFarmer_,
address bidTicket_
) {
_initializeOwner(owner_);
theBarn = theBarn_;
theFarmer = theFarmer_;
bidTicket = IBidTicket(bidTicket_);
}
function startAuctionERC721(
uint256 startingBid,
address tokenAddress,
uint256[] calldata tokenIds
) external payable nonReentrant {
uint256 length = tokenIds.length;
require(startingBid >= minStartingBid, StartPriceTooLow());
require(length > 0, InvalidLengthOfTokenIds());
require(length <= maxTokens, MaxTokensPerTxReached());
_processPayment(startingBid);
Auction storage auction = auctions[nextAuctionId];
auction.auctionType = AUCTION_TYPE_ERC721;
auction.tokenAddress = tokenAddress;
auction.endTime = uint64(block.timestamp + auctionDuration);
auction.highestBidder = msg.sender;
auction.highestBid = startingBid;
auction.tokenCount = uint8(length);
auction.bidderCount = 1;
auction.bidDelta = startingBid;
mapping(uint256 => uint256) storage tokenMap = auction.tokenIds;
for (uint256 i; i < length; ++i) {
tokenMap[i] = tokenIds[i];
}
unchecked {
++nextAuctionId;
}
emit Started(msg.sender, tokenAddress, tokenIds);
bidTicket.burn(msg.sender, bidTicketTokenId, bidTicketCostStart);
_validateAuctionTokensERC721(tokenAddress, tokenIds);
}
function startAuctionERC1155(
uint256 startingBid,
address tokenAddress,
uint256[] calldata tokenIds,
uint256[] calldata amounts
) external payable nonReentrant {
uint256 length = tokenIds.length;
require(startingBid >= minStartingBid, StartPriceTooLow());
require(length > 0, InvalidLengthOfTokenIds());
require(length == amounts.length, InvalidLengthOfAmounts());
_processPayment(startingBid);
Auction storage auction = auctions[nextAuctionId];
auction.auctionType = AUCTION_TYPE_ERC1155;
auction.tokenAddress = tokenAddress;
auction.endTime = uint64(block.timestamp + auctionDuration);
auction.highestBidder = msg.sender;
auction.highestBid = startingBid;
auction.tokenCount = uint8(length);
auction.bidderCount = 1;
auction.bidDelta = startingBid;
mapping(uint256 => uint256) storage tokenMap = auction.tokenIds;
mapping(uint256 => uint256) storage amountMap = auction.amounts;
for (uint256 i; i < length; ++i) {
tokenMap[i] = tokenIds[i];
amountMap[i] = amounts[i];
}
unchecked {
++nextAuctionId;
}
emit Started(msg.sender, tokenAddress, tokenIds);
bidTicket.burn(msg.sender, bidTicketTokenId, bidTicketCostStart);
_validateAuctionTokensERC1155(tokenAddress, tokenIds, amounts);
}
function bid(uint256 auctionId, uint256 bidAmount) external payable nonReentrant {
Auction storage auction = auctions[auctionId];
require(auction.status == Status.Active, InvalidStatus());
require(auction.highestBidder != msg.sender, IsHighestBidder());
require(bidAmount >= auction.highestBid + minBidIncrement, BidTooLow());
require(block.timestamp <= auction.endTime, AuctionEnded());
if (block.timestamp > auction.endTime - antiSnipeDuration) {
auction.endTime += uint64(antiSnipeDuration);
}
_processPayment(bidAmount);
address prevHighestBidder = auction.highestBidder;
uint256 prevHighestBid = auction.highestBid;
unchecked {
balances[prevHighestBidder] += prevHighestBid;
if (auction.rewards[prevHighestBidder] == 0) {
auction.bidders[auction.bidderCount - 1] = prevHighestBidder;
++auction.bidderCount;
}
uint256 reward = auction.bidDelta * outbidRewardPercent / 100;
auction.rewards[prevHighestBidder] += reward;
auction.bidDelta = bidAmount - prevHighestBid;
}
auction.highestBidder = msg.sender;
auction.highestBid = bidAmount;
emit NewBid(auctionId, msg.sender, bidAmount);
bidTicket.burn(msg.sender, bidTicketTokenId, bidTicketCostBid);
}
function claim(uint256 auctionId) external nonReentrant {
Auction storage auction = auctions[auctionId];
require(auction.status == Status.Active, InvalidStatus());
require(block.timestamp > auction.endTime, AuctionNotEnded());
require(msg.sender == auction.highestBidder || msg.sender == owner(), NotHighestBidder());
auction.status = Status.Claimed;
uint256 totalRewards = _distributeRewards(auction);
emit Claimed(auctionId, auction.highestBidder);
(bool success,) = payable(theFarmer).call{value: auction.highestBid - totalRewards}("");
require(success, TransferFailed());
if (auction.auctionType == AUCTION_TYPE_ERC721) {
_transferERC721s(auction);
} else {
_transferERC1155s(auction);
}
}
function refund(uint256 auctionId) external nonReentrant {
Auction storage auction = auctions[auctionId];
uint256 highestBid = auction.highestBid;
uint256 endTime = auction.endTime;
require(auction.status == Status.Active, InvalidStatus());
require(block.timestamp > endTime, AuctionActive());
require(block.timestamp <= endTime + settlementDuration, SettlementPeriodEnded());
require(msg.sender == auction.highestBidder || msg.sender == owner(), NotHighestBidder());
auction.status = Status.Refunded;
emit Refunded(auctionId, auction.highestBidder, highestBid);
if (auction.auctionType == AUCTION_TYPE_ERC721) {
_checkAndResetERC721s(auction);
} else {
_checkAndResetERC1155s(auction);
}
unchecked {
balances[auction.highestBidder] += highestBid;
}
}
function abandon(uint256 auctionId) external onlyOwner nonReentrant {
Auction storage auction = auctions[auctionId];
address highestBidder = auction.highestBidder;
uint256 highestBid = auction.highestBid;
require(auction.status == Status.Active, InvalidStatus());
require(block.timestamp > auction.endTime + settlementDuration, SettlementPeriodNotExpired());
auction.status = Status.Abandoned;
if (auction.auctionType == AUCTION_TYPE_ERC721) {
_resetERC721s(auction);
} else {
_resetERC1155s(auction);
}
uint256 fee;
unchecked {
fee = highestBid * abandonmentFeePercent / 100;
balances[highestBidder] += highestBid - fee;
}
emit Abandoned(auctionId, highestBidder, fee);
(bool success,) = payable(theFarmer).call{value: fee}("");
require(success, TransferFailed());
}
function withdraw() external nonReentrant {
uint256 balance = balances[msg.sender];
require(balance > 0, NoBalanceToWithdraw());
balances[msg.sender] = 0;
emit Withdraw(msg.sender, balance);
(bool success,) = payable(msg.sender).call{value: balance}("");
require(success, TransferFailed());
}
function getAuctionTokens(uint256 auctionId) external view returns (uint256[] memory, uint256[] memory) {
Auction storage auction = auctions[auctionId];
uint256[] memory tokenIds = new uint256[](auction.tokenCount);
uint256[] memory amounts = new uint256[](auction.tokenCount);
uint256 tokenCount = auction.tokenCount;
for (uint256 i; i < tokenCount; ++i) {
tokenIds[i] = auction.tokenIds[i];
if (auction.auctionType == AUCTION_TYPE_ERC721) {
amounts[i] = 1;
} else {
amounts[i] = auction.amounts[i];
}
}
return (tokenIds, amounts);
}
function getPendingRewards(address bidder, uint256[] calldata auctionIds) external view returns (uint256) {
uint256 totalRewards;
uint256 length = auctionIds.length;
for (uint256 i; i < length; ++i) {
if (auctions[auctionIds[i]].status == Status.Active) {
totalRewards += auctions[auctionIds[i]].rewards[bidder];
}
}
return totalRewards;
}
function getClaimedAuctions(uint256 limit) external view returns (uint256[] memory) {
uint256[] memory claimedAuctions = new uint256[](limit);
uint256 count = 0;
for (uint256 i = nextAuctionId - 1; i > 0 && count < limit; --i) {
if (auctions[i].status == Status.Claimed) {
claimedAuctions[count] = i;
unchecked { ++count; }
}
}
assembly {
mstore(claimedAuctions, count)
}
return claimedAuctions;
}
function setBarnAddress(address theBarn_) external onlyOwner {
theBarn = theBarn_;
}
function setFarmerAddress(address theFarmer_) external onlyOwner {
theFarmer = theFarmer_;
}
function setBidTicketAddress(address bidTicket_) external onlyOwner {
bidTicket = IBidTicket(bidTicket_);
}
function setBidTicketTokenId(uint256 bidTicketTokenId_) external onlyOwner {
bidTicketTokenId = bidTicketTokenId_;
}
function setBidTicketCostStart(uint256 bidTicketCostStart_) external onlyOwner {
bidTicketCostStart = bidTicketCostStart_;
}
function setBidTicketCostBid(uint256 bidTicketCostBid_) external onlyOwner {
bidTicketCostBid = bidTicketCostBid_;
}
function setMaxTokens(uint256 maxTokens_) external onlyOwner {
maxTokens = maxTokens_;
}
function setMinStartingBid(uint256 minStartingBid_) external onlyOwner {
minStartingBid = minStartingBid_;
}
function setMinBidIncrement(uint256 minBidIncrement_) external onlyOwner {
minBidIncrement = minBidIncrement_;
}
function setAuctionDuration(uint256 auctionDuration_) external onlyOwner {
auctionDuration = auctionDuration_;
}
function setSettlementDuration(uint256 settlementDuration_) external onlyOwner {
settlementDuration = settlementDuration_;
}
function setAntiSnipeDuration(uint256 antiSnipeDuration_) external onlyOwner {
antiSnipeDuration = antiSnipeDuration_;
}
function setAbandonmentFeePercent(uint256 newFeePercent) external onlyOwner {
require(newFeePercent <= 100, InvalidFeePercentage());
abandonmentFeePercent = newFeePercent;
}
function setOutbidRewardPercent(uint256 newPercent) external onlyOwner {
require(newPercent <= 100, InvalidFeePercentage());
outbidRewardPercent = newPercent;
}
function _processPayment(uint256 payment) internal {
uint256 balance = balances[msg.sender];
uint256 paymentFromBalance;
uint256 paymentFromMsgValue;
if (balance >= payment) {
paymentFromBalance = payment;
paymentFromMsgValue = 0;
} else {
paymentFromBalance = balance;
paymentFromMsgValue = payment - balance;
}
require(msg.value == paymentFromMsgValue, InvalidValue());
if (paymentFromBalance > 0) {
balances[msg.sender] -= paymentFromBalance;
}
}
function _validateAuctionTokensERC721(address tokenAddress, uint256[] calldata tokenIds) internal {
IERC721 erc721Contract = IERC721(tokenAddress);
uint256 length = tokenIds.length;
mapping(uint256 => bool) storage auctionTokens = auctionTokensERC721[tokenAddress];
for (uint256 i; i < length; ++i) {
uint256 tokenId = tokenIds[i];
require(!auctionTokens[tokenId], TokenAlreadyInAuction());
auctionTokens[tokenId] = true;
require(erc721Contract.ownerOf(tokenId) == theBarn, TokenNotOwned());
}
}
function _validateAuctionTokensERC1155(
address tokenAddress,
uint256[] calldata tokenIds,
uint256[] calldata amounts
) internal {
IERC1155 erc1155Contract = IERC1155(tokenAddress);
uint256 totalTokens;
uint256 totalNeeded;
uint256 balance;
uint256 tokenId;
uint256 amount;
mapping(uint256 => uint256) storage auctionTokens = auctionTokensERC1155[tokenAddress];
uint256 length = tokenIds.length;
for (uint256 i; i < length; ++i) {
tokenId = tokenIds[i];
amount = amounts[i];
totalTokens += amount;
totalNeeded = auctionTokens[tokenId] + amount;
balance = erc1155Contract.balanceOf(theBarn, tokenId);
require(totalNeeded <= balance, NotEnoughTokensInSupply());
unchecked {
auctionTokens[tokenId] += amount;
}
}
require(totalTokens <= maxTokens, MaxTokensPerTxReached());
}
function _transferERC721s(Auction storage auction) internal {
address tokenAddress = auction.tokenAddress;
uint256 tokenCount = auction.tokenCount;
address highestBidder = auction.highestBidder;
IERC721 erc721Contract = IERC721(tokenAddress);
mapping(uint256 => uint256) storage tokenMap = auction.tokenIds;
mapping(uint256 => bool) storage auctionTokens = auctionTokensERC721[tokenAddress];
for (uint256 i; i < tokenCount; ++i) {
auctionTokens[tokenMap[i]] = false;
}
for (uint256 i; i < tokenCount; ++i) {
erc721Contract.safeTransferFrom(theBarn, highestBidder, tokenMap[i]);
}
}
function _transferERC1155s(Auction storage auction) internal {
address tokenAddress = auction.tokenAddress;
IERC1155 erc1155Contract = IERC1155(tokenAddress);
uint256 tokenCount = auction.tokenCount;
uint256[] memory tokenIds = new uint256[](tokenCount);
uint256[] memory amounts = new uint256[](tokenCount);
mapping(uint256 => uint256) storage tokenMap = auction.tokenIds;
mapping(uint256 => uint256) storage amountMap = auction.amounts;
mapping(uint256 => uint256) storage auctionTokens = auctionTokensERC1155[tokenAddress];
for (uint256 i; i < tokenCount; ++i) {
uint256 tokenId = tokenMap[i];
uint256 amount = amountMap[i];
tokenIds[i] = tokenId;
amounts[i] = amount;
auctionTokens[tokenId] -= amount;
}
erc1155Contract.safeBatchTransferFrom(theBarn, auction.highestBidder, tokenIds, amounts, "");
}
function _resetERC721s(Auction storage auction) internal {
address tokenAddress = auction.tokenAddress;
uint256 tokenCount = auction.tokenCount;
mapping(uint256 => uint256) storage tokenMap = auction.tokenIds;
mapping(uint256 => bool) storage auctionTokens = auctionTokensERC721[tokenAddress];
for (uint256 i; i < tokenCount; ++i) {
uint256 tokenId = tokenMap[i];
auctionTokens[tokenId] = false;
}
}
function _resetERC1155s(Auction storage auction) internal {
address tokenAddress = auction.tokenAddress;
uint256 tokenCount = auction.tokenCount;
uint256[] memory tokenIds = new uint256[](tokenCount);
uint256[] memory amounts = new uint256[](tokenCount);
mapping(uint256 => uint256) storage tokenMap = auction.tokenIds;
mapping(uint256 => uint256) storage amountMap = auction.amounts;
mapping(uint256 => uint256) storage auctionTokens = auctionTokensERC1155[tokenAddress];
for (uint256 i; i < tokenCount; ++i) {
uint256 tokenId = tokenMap[i];
uint256 amount = amountMap[i];
tokenIds[i] = tokenId;
amounts[i] = amount;
auctionTokens[tokenId] -= amount;
}
}
function _checkAndResetERC721s(Auction storage auction) internal {
address tokenAddress = auction.tokenAddress;
uint256 tokenCount = auction.tokenCount;
mapping(uint256 => uint256) storage tokenMap = auction.tokenIds;
mapping(uint256 => bool) storage auctionTokens = auctionTokensERC721[tokenAddress];
bool notRefundable = IERC721(tokenAddress).isApprovedForAll(theBarn, address(this));
for (uint256 i; i < tokenCount; ++i) {
uint256 tokenId = tokenMap[i];
auctionTokens[tokenId] = false;
notRefundable = notRefundable && (IERC721(tokenAddress).ownerOf(tokenId) == theBarn);
}
require(!notRefundable, AuctionIsApproved());
}
function _checkAndResetERC1155s(Auction storage auction) internal {
address tokenAddress = auction.tokenAddress;
uint256 tokenCount = auction.tokenCount;
uint256[] memory tokenIds = new uint256[](tokenCount);
uint256[] memory amounts = new uint256[](tokenCount);
mapping(uint256 => uint256) storage tokenMap = auction.tokenIds;
mapping(uint256 => uint256) storage amountMap = auction.amounts;
mapping(uint256 => uint256) storage auctionTokens = auctionTokensERC1155[tokenAddress];
bool notRefundable = IERC1155(tokenAddress).isApprovedForAll(theBarn, address(this));
for (uint256 i; i < tokenCount; ++i) {
uint256 tokenId = tokenMap[i];
uint256 amount = amountMap[i];
tokenIds[i] = tokenId;
amounts[i] = amount;
auctionTokens[tokenId] -= amount;
notRefundable = notRefundable && (IERC1155(tokenAddress).balanceOf(theBarn, tokenId) >= amount);
}
require(!notRefundable, AuctionIsApproved());
}
function _distributeRewards(Auction storage auction) internal returns (uint256) {
uint256 totalRewards;
uint256 length = auction.bidderCount;
for (uint256 i; i < length; ++i) {
address bidder = auction.bidders[i];
uint256 reward = auction.rewards[bidder];
if (reward > 0) {
unchecked {
balances[bidder] += reward;
totalRewards += reward;
}
}
}
return totalRewards;
}
}
文件 2 的 9:IAuctions.sol
pragma solidity 0.8.27;
interface IAuctions {
function startAuctionERC721(uint256 startingBid, address tokenAddress, uint256[] calldata tokenIds) external payable;
function startAuctionERC1155(uint256 startingBid, address tokenAddress, uint256[] calldata tokenIds, uint256[] calldata amounts) external payable;
function bid(uint256 auctionId, uint256 bidAmount) external payable;
function claim(uint256 auctionId) external;
function refund(uint256 auctionId) external;
function abandon(uint256 auctionId) external;
function withdraw() external;
function getAuctionTokens(uint256 auctionId) external view returns (uint256[] memory, uint256[] memory);
function getPendingRewards(address bidder, uint256[] calldata auctionIds) external view returns (uint256);
function getClaimedAuctions(uint256 limit) external view returns (uint256[] memory);
function setBarnAddress(address theBarn_) external;
function setFarmerAddress(address theFarmer_) external;
function setBidTicketAddress(address bidTicket_) external;
function setBidTicketTokenId(uint256 bidTicketTokenId_) external;
function setBidTicketCostStart(uint256 bidTicketCostStart_) external;
function setBidTicketCostBid(uint256 bidTicketCostBid_) external;
function setMaxTokens(uint256 maxTokens_) external;
function setMinStartingBid(uint256 minStartingBid_) external;
function setMinBidIncrement(uint256 minBidIncrement_) external;
function setAuctionDuration(uint256 auctionDuration_) external;
function setSettlementDuration(uint256 settlementDuration_) external;
function setAntiSnipeDuration(uint256 antiSnipeDuration_) external;
function setAbandonmentFeePercent(uint256 newFeePercent) external;
function setOutbidRewardPercent(uint256 newPercent) external;
event Abandoned(uint256 indexed auctionId, address indexed bidder, uint256 indexed fee);
event Claimed(uint256 indexed auctionId, address indexed winner);
event NewBid(uint256 indexed auctionId, address indexed bidder, uint256 indexed value);
event Refunded(uint256 indexed auctionId, address indexed bidder, uint256 indexed value);
event Started(address indexed bidder, address indexed tokenAddress, uint256[] indexed tokenIds);
event Withdraw(address indexed user, uint256 indexed value);
error AuctionActive();
error AuctionEnded();
error AuctionIsApproved();
error AuctionNotEnded();
error BidTooLow();
error InvalidFeePercentage();
error InvalidLengthOfAmounts();
error InvalidLengthOfTokenIds();
error InvalidStatus();
error InvalidValue();
error IsHighestBidder();
error MaxTokensPerTxReached();
error NoBalanceToWithdraw();
error NoRewardsToClaim();
error NotEnoughTokensInSupply();
error NotHighestBidder();
error SettlementPeriodNotExpired();
error SettlementPeriodEnded();
error StartPriceTooLow();
error TokenAlreadyInAuction();
error TokenNotOwned();
error TransferFailed();
}
文件 3 的 9:IBidTicket.sol
pragma solidity 0.8.27;
import "ERC1155P/contracts/IERC1155P.sol";
interface IBidTicket is IERC1155P {
function setURI(uint256 tokenId, string calldata tokenURI) external;
function mint(address to, uint256 id, uint256 amount) external;
function mintBatch(address to, uint256[] calldata ids, uint256[] calldata amounts) external;
function burn(address from, uint256 id, uint256 amount) external;
function burnBatch(address from, uint256[] calldata ids, uint256[] calldata amounts) external;
function setHarvestContract(address harvestContract_) external;
function setAuctionsContract(address auctionsContract_) external;
}
文件 4 的 9:IERC1155.sol
pragma solidity ^0.8.20;
import {IERC165} from "../../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 value, bytes calldata data) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external;
}
文件 5 的 9:IERC1155P.sol
pragma solidity ^0.8.20;
interface IERC1155P {
error BalanceQueryForZeroAddress();
error ArrayLengthMismatch();
error BurnFromZeroAddress();
error MintToZeroAddress();
error MintZeroQuantity();
error BurnExceedsBalance();
error TransferExceedsBalance();
error ExceedsMaximumBalance();
error TransferCallerNotOwnerNorApproved();
error TransferToNonERC1155ReceiverImplementer();
error TransferToZeroAddress();
error ExceedsMaximumTokenId();
function supportsInterface(bytes4 interfaceId) external view returns (bool);
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;
}
文件 6 的 9:IERC165.sol
pragma solidity ^0.8.20;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 7 的 9:IERC721.sol
pragma solidity ^0.8.20;
import {IERC165} from "../../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);
}
文件 8 的 9:Ownable.sol
pragma solidity ^0.8.4;
abstract contract Ownable {
error Unauthorized();
error NewOwnerIsZeroAddress();
error NoHandoverRequest();
error AlreadyInitialized();
event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
event OwnershipHandoverRequested(address indexed pendingOwner);
event OwnershipHandoverCanceled(address indexed pendingOwner);
uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;
uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;
uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;
bytes32 internal constant _OWNER_SLOT =
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;
uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;
function _guardInitializeOwner() internal pure virtual returns (bool guard) {}
function _initializeOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
assembly {
let ownerSlot := _OWNER_SLOT
if sload(ownerSlot) {
mstore(0x00, 0x0dc149f0)
revert(0x1c, 0x04)
}
newOwner := shr(96, shl(96, newOwner))
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
} else {
assembly {
newOwner := shr(96, shl(96, newOwner))
sstore(_OWNER_SLOT, newOwner)
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
}
}
function _setOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
assembly {
let ownerSlot := _OWNER_SLOT
newOwner := shr(96, shl(96, newOwner))
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
}
} else {
assembly {
let ownerSlot := _OWNER_SLOT
newOwner := shr(96, shl(96, newOwner))
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
sstore(ownerSlot, newOwner)
}
}
}
function _checkOwner() internal view virtual {
assembly {
if iszero(eq(caller(), sload(_OWNER_SLOT))) {
mstore(0x00, 0x82b42900)
revert(0x1c, 0x04)
}
}
}
function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
return 48 * 3600;
}
function transferOwnership(address newOwner) public payable virtual onlyOwner {
assembly {
if iszero(shl(96, newOwner)) {
mstore(0x00, 0x7448fbae)
revert(0x1c, 0x04)
}
}
_setOwner(newOwner);
}
function renounceOwnership() public payable virtual onlyOwner {
_setOwner(address(0));
}
function requestOwnershipHandover() public payable virtual {
unchecked {
uint256 expires = block.timestamp + _ownershipHandoverValidFor();
assembly {
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), expires)
log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
}
}
}
function cancelOwnershipHandover() public payable virtual {
assembly {
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), 0)
log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
}
}
function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
assembly {
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
let handoverSlot := keccak256(0x0c, 0x20)
if gt(timestamp(), sload(handoverSlot)) {
mstore(0x00, 0x6f5e8818)
revert(0x1c, 0x04)
}
sstore(handoverSlot, 0)
}
_setOwner(pendingOwner);
}
function owner() public view virtual returns (address result) {
assembly {
result := sload(_OWNER_SLOT)
}
}
function ownershipHandoverExpiresAt(address pendingOwner)
public
view
virtual
returns (uint256 result)
{
assembly {
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
result := sload(keccak256(0x0c, 0x20))
}
}
modifier onlyOwner() virtual {
_checkOwner();
_;
}
}
文件 9 的 9:ReentrancyGuard.sol
pragma solidity ^0.8.4;
abstract contract ReentrancyGuard {
error Reentrancy();
uint256 private constant _REENTRANCY_GUARD_SLOT = 0x929eee149b4bd21268;
modifier nonReentrant() virtual {
assembly {
if eq(sload(_REENTRANCY_GUARD_SLOT), address()) {
mstore(0x00, 0xab143c06)
revert(0x1c, 0x04)
}
sstore(_REENTRANCY_GUARD_SLOT, address())
}
_;
assembly {
sstore(_REENTRANCY_GUARD_SLOT, codesize())
}
}
modifier nonReadReentrant() virtual {
assembly {
if eq(sload(_REENTRANCY_GUARD_SLOT), address()) {
mstore(0x00, 0xab143c06)
revert(0x1c, 0x04)
}
}
_;
}
}
{
"compilationTarget": {
"src/Auctions.sol": "Auctions"
},
"evmVersion": "cancun",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 100000
},
"remappings": [
":@openzeppelin/=lib/openzeppelin-contracts/",
":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
":ERC1155P/=lib/ERC1155P/",
":ds-test/=lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":solady/=lib/solady/src/"
],
"viaIR": true
}
[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"theBarn_","type":"address"},{"internalType":"address","name":"theFarmer_","type":"address"},{"internalType":"address","name":"bidTicket_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"AuctionActive","type":"error"},{"inputs":[],"name":"AuctionEnded","type":"error"},{"inputs":[],"name":"AuctionIsApproved","type":"error"},{"inputs":[],"name":"AuctionNotEnded","type":"error"},{"inputs":[],"name":"BidTooLow","type":"error"},{"inputs":[],"name":"InvalidFeePercentage","type":"error"},{"inputs":[],"name":"InvalidLengthOfAmounts","type":"error"},{"inputs":[],"name":"InvalidLengthOfTokenIds","type":"error"},{"inputs":[],"name":"InvalidStatus","type":"error"},{"inputs":[],"name":"InvalidValue","type":"error"},{"inputs":[],"name":"IsHighestBidder","type":"error"},{"inputs":[],"name":"MaxTokensPerTxReached","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoBalanceToWithdraw","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NoRewardsToClaim","type":"error"},{"inputs":[],"name":"NotEnoughTokensInSupply","type":"error"},{"inputs":[],"name":"NotHighestBidder","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"inputs":[],"name":"SettlementPeriodEnded","type":"error"},{"inputs":[],"name":"SettlementPeriodNotExpired","type":"error"},{"inputs":[],"name":"StartPriceTooLow","type":"error"},{"inputs":[],"name":"TokenAlreadyInAuction","type":"error"},{"inputs":[],"name":"TokenNotOwned","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"bidder","type":"address"},{"indexed":true,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"Abandoned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"winner","type":"address"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"bidder","type":"address"},{"indexed":true,"internalType":"uint256","name":"value","type":"uint256"}],"name":"NewBid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"bidder","type":"address"},{"indexed":true,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Refunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bidder","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"Started","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"abandon","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"abandonmentFeePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"antiSnipeDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"auctionDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"auctionTokensERC1155","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"auctionTokensERC721","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"auctions","outputs":[{"internalType":"uint8","name":"auctionType","type":"uint8"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint8","name":"tokenCount","type":"uint8"},{"internalType":"enum Status","name":"status","type":"uint8"},{"internalType":"address","name":"highestBidder","type":"address"},{"internalType":"uint256","name":"highestBid","type":"uint256"},{"internalType":"uint256","name":"bidDelta","type":"uint256"},{"internalType":"uint256","name":"bidderCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"},{"internalType":"uint256","name":"bidAmount","type":"uint256"}],"name":"bid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"bidTicket","outputs":[{"internalType":"contract IBidTicket","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bidTicketCostBid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bidTicketCostStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bidTicketTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"getAuctionTokens","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"getClaimedAuctions","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bidder","type":"address"},{"internalType":"uint256[]","name":"auctionIds","type":"uint256[]"}],"name":"getPendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minBidIncrement","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minStartingBid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextAuctionId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"outbidRewardPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeePercent","type":"uint256"}],"name":"setAbandonmentFeePercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"antiSnipeDuration_","type":"uint256"}],"name":"setAntiSnipeDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionDuration_","type":"uint256"}],"name":"setAuctionDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"theBarn_","type":"address"}],"name":"setBarnAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bidTicket_","type":"address"}],"name":"setBidTicketAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bidTicketCostBid_","type":"uint256"}],"name":"setBidTicketCostBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bidTicketCostStart_","type":"uint256"}],"name":"setBidTicketCostStart","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bidTicketTokenId_","type":"uint256"}],"name":"setBidTicketTokenId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"theFarmer_","type":"address"}],"name":"setFarmerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxTokens_","type":"uint256"}],"name":"setMaxTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minBidIncrement_","type":"uint256"}],"name":"setMinBidIncrement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minStartingBid_","type":"uint256"}],"name":"setMinStartingBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPercent","type":"uint256"}],"name":"setOutbidRewardPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"settlementDuration_","type":"uint256"}],"name":"setSettlementDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settlementDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"startingBid","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"startAuctionERC1155","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startingBid","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"startAuctionERC721","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"theBarn","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"theFarmer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]