编译器
0.8.20+commit.a1b79de6
文件 1 的 9:IPermissions.sol
pragma solidity ^0.8.0;
interface IPermissions {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 2 的 9:IProductMarket.sol
pragma solidity ^0.8.20;
interface IProductMarket {
struct ListingParams {
uint24 productId;
uint16 quantity;
uint16 reserved;
uint16 vipLimit;
uint16 pubLimit;
uint64 vipPrice;
uint64 pubPrice;
uint32 endTimestamp;
uint32 vipStartTimestamp;
uint32 pubStartTimestamp;
bool enabled;
}
struct Listing {
uint24 productId;
uint8 enabled;
uint16 quantity;
uint16 reserved;
uint16 vipLimit;
uint16 pubLimit;
uint64 vipPrice;
uint64 pubPrice;
uint32 endTimestamp;
uint32 vipStartTimestamp;
uint32 pubStartTimestamp;
uint16 resPurchased;
uint16 vipPurchased;
uint16 pubPurchased;
uint72 vipIncome;
uint72 pubIncome;
}
struct ListingQuery {
uint256 listingId;
Listing listingData;
}
enum AuctionStatus {
UNSET,
CREATED,
COMPLETED,
CANCELLED
}
struct AuctionParams {
uint56 productId;
uint32 startTimestamp;
uint32 endTimestamp;
uint64 bidBufferBps;
uint64 timeBufferSeconds;
uint256 minimumBidAmount;
uint256 reserveBidAmount;
}
struct Auction {
uint56 productId;
AuctionStatus status;
uint32 startTimestamp;
uint32 endTimestamp;
uint64 bidBufferBps;
uint64 timeBufferSeconds;
uint256 minimumBidAmount;
uint256 reserveBidAmount;
}
struct AuctionQuery {
uint256 auctionId;
Auction auctionData;
Bid winningBid;
}
struct Bid {
uint64 auctionId;
uint32 bidTimestamp;
address bidder;
uint256 bidAmount;
}
struct BidHistory {
uint256 count;
mapping(uint256 => Bid) bids;
}
struct ProductLookup {
uint256 count;
mapping(uint256 => uint256) id;
}
event ListingAdded(uint256 indexed listingId, Listing listing);
event ListingUpdated(uint256 indexed listingId, Listing listing);
event ListingEnabled(uint256 indexed listingId, bool indexed enabled);
event ListingContract(uint256 indexed listingId, address indexed tokenContract);
event NewSale(
uint256 indexed listingId,
address indexed buyer,
address indexed recipient,
uint256 productId,
uint256 quantity,
uint256 price
);
event WithdrawalRecipientApproved(address indexed recipient, bool indexed approved);
event IncomeWithdrawal(
address indexed operator,
address indexed recipient,
uint256 indexed amount
);
event AuctionAdded(uint256 indexed auctionId, Auction auction);
event AuctionUpdated(uint256 indexed auctionId, Auction auction);
event AuctionCancelled(uint256 indexed auctionId);
event AuctionContract(uint256 indexed auctionId, address indexed tokenContract);
event AuctionClosed(
uint256 indexed auctionId,
address indexed bidder,
uint256 indexed bidAmount,
uint256 productId,
bool tokenAwarded,
bool bidRefunded
);
event NewBid(
uint256 indexed auctionId,
address indexed bidder,
uint256 indexed bidAmount,
Auction auction
);
error FinanceRoleRequired();
error ManagerRoleRequired();
error ListingVipStartAfterPubStart(
uint32 vipStartTimestamp,
uint32 pubStartTimestamp
);
error ListingPubStartAfterEnd(uint32 pubStartTimestamp, uint32 endTimestamp);
error ListingReserveExceedsQuantity(uint16 reserved, uint16 quantity);
error ListingDoesNotExist();
error ListingPurchasesExceedsQuantity(uint16 quantity, uint256 purchased);
error ListingPurchasesExceedsReserve(uint16 reserve, uint256 purchased);
error ListingNotEnabled();
error ListingHasEnded();
error ListingQueryInvalidRange();
error ListingExpectedPriceNotEqualValue(
uint256 expectedTotalPrice,
uint256 transactionValue
);
error ListingInsufficientQuantity(
uint256 requestedQuantity,
uint256 availableQuantity
);
error ListingVipSaleNotStarted(uint64 vipStartTime, uint256 currentTimestamp);
error ListingPublicSaleNotStarted(uint64 publicStartTime, uint256 currentTimestamp);
error ListingVipLimitExceeded(uint256 purchases, uint256 limit);
error ListingVipReserveExceeded(uint256 requestedQuantity, uint256 availableQuantity);
error ListingPublicLimitExceeded(uint256 purchases, uint256 limit);
error ListingVipExpectedPriceInvalid(
uint256 expectedTotalPrice,
uint256 actualTotalPrice
);
error ListingPublicExpectedPriceInvalid(
uint256 expectedTotalPrice,
uint256 actualTotalPrice
);
error AuctionQueryInvalidRange();
error AuctionStartAfterEnd(uint32 startTimestamp, uint32 endTimestamp);
error AuctionBufferBpsExceedsMax();
error AuctionDoesNotExist();
error AuctionNotActive();
error AuctionNotEnded(uint32 endTimestamp, uint256 currentTimestamp);
error AuctionHasBids(uint256 numberOfBids);
error AuctionHasNoBids();
error AuctionReserveNotMet(uint256 highestBidAmount, uint256 reserveBidAmount);
error AuctionReserveWasMet(uint256 highestBidAmount, uint256 reserveBidAmount);
error AuctionPreviousBidRefundRejected();
error AuctionNotStarted(uint32 startTimestamp, uint256 currentTimestamp);
error AuctionHasEnded();
error AuctionBidAmountZero();
error AuctionBidBelowMinimum(uint256 bidAmount, uint256 minimumBidAmount);
error AuctionBidAmountNotEqualValue(uint256 bidAmount, uint256 transactionValue);
error AuctionBidAmountInsufficient(uint256 bidAmount, uint256 requiredBidAmount);
error WithdrawalRecipientNotApproved();
error WithdrawalRecipientRejectedTransfer();
error WithdrawalInsufficientBalance(uint256 requested, uint256 available);
}
文件 3 的 9:IProductToken.sol
pragma solidity ^0.8.20;
interface IProductToken {
function mintTo(address _to, uint256 _productId) external;
function mintTo(address _to, uint256 _productId, bytes memory _data) external;
function mintTo(
address _to,
uint256 _productId,
string calldata _uri,
bytes memory _data
) external;
function batchMintTo(address _to, uint256 _productId, uint256 _quantity) external;
function batchMintTo(
address _to,
uint256 _productId,
uint256 _quantity,
bytes memory _data
) external;
function batchMintTo(
address _to,
uint256 _productId,
uint256 _quantity,
string[] calldata _uris,
bytes memory _data
) external;
event GlobalMintingRestricted(bool restricted);
event GlobalTransfersRestricted(bool restricted);
event GlobalBurningRestricted(bool restricted);
error BatchMintURICountMismatch();
error ManagerRoleRequired();
error MintingRoleRequired();
error GlobalMintingDisabled();
error GlobalTransfersDisabled();
error GlobalBurningDisabled();
}
文件 4 的 9:IVipManager.sol
pragma solidity ^0.8.20;
interface IVipManager {
struct VipConditions {
GroupConditions groupConditions;
ProductConditions[] productConditions;
ERC721Conditions[] erc721Conditions;
ERC1155Conditions[] erc1155Conditions;
}
struct VipConditionsData {
uint256 productLength;
uint256 erc721Length;
uint256 erc1155Length;
GroupConditions groupConditions;
mapping(uint256 => ERC721Conditions) erc721Conditions;
mapping(uint256 => ERC1155ConditionsData) erc1155Conditions;
mapping(uint256 => ProductConditionsData) productConditions;
}
struct GroupConditions {
address groupContract;
uint256 groupId;
}
struct ERC721Conditions {
address tokenContract;
}
struct ProductConditions {
address tokenContract;
uint256[] productIds;
}
struct ERC1155Conditions {
address tokenContract;
uint256[] tokenIds;
}
struct ERC1155ConditionsData {
address tokenContract;
uint96 length;
mapping(uint256 => uint256) tokenIds;
}
struct ProductConditionsData {
address tokenContract;
uint96 length;
mapping(uint256 => uint256) productIds;
}
function isVip(uint256 _selectorId, address _member) external view returns (bool);
error ManagerRoleRequired();
event VipSelectorConditionsUpdated(
uint256 indexed selectorId,
uint256 indexed conditionsId
);
event VipConditionsUpdated(uint256 indexed conditionsId, VipConditions conditions);
}
文件 5 的 9:Permissions.sol
pragma solidity ^0.8.0;
import "./interface/IPermissions.sol";
import "../lib/TWStrings.sol";
contract Permissions is IPermissions {
mapping(bytes32 => mapping(address => bool)) private _hasRole;
mapping(bytes32 => bytes32) private _getRoleAdmin;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
modifier onlyRole(bytes32 role) {
_checkRole(role, msg.sender);
_;
}
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _hasRole[role][account];
}
function hasRoleWithSwitch(bytes32 role, address account) public view returns (bool) {
if (!_hasRole[role][address(0)]) {
return _hasRole[role][account];
}
return true;
}
function getRoleAdmin(bytes32 role) external view override returns (bytes32) {
return _getRoleAdmin[role];
}
function grantRole(bytes32 role, address account) public virtual override {
_checkRole(_getRoleAdmin[role], msg.sender);
if (_hasRole[role][account]) {
revert("Can only grant to non holders");
}
_setupRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual override {
_checkRole(_getRoleAdmin[role], msg.sender);
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual override {
if (msg.sender != account) {
revert("Can only renounce for self");
}
_revokeRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = _getRoleAdmin[role];
_getRoleAdmin[role] = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _setupRole(bytes32 role, address account) internal virtual {
_hasRole[role][account] = true;
emit RoleGranted(role, account, msg.sender);
}
function _revokeRole(bytes32 role, address account) internal virtual {
_checkRole(role, account);
delete _hasRole[role][account];
emit RoleRevoked(role, account, msg.sender);
}
function _checkRole(bytes32 role, address account) internal view virtual {
if (!_hasRole[role][account]) {
revert(
string(
abi.encodePacked(
"Permissions: account ",
TWStrings.toHexString(uint160(account), 20),
" is missing role ",
TWStrings.toHexString(uint256(role), 32)
)
)
);
}
}
function _checkRoleWithSwitch(bytes32 role, address account) internal view virtual {
if (!hasRoleWithSwitch(role, account)) {
revert(
string(
abi.encodePacked(
"Permissions: account ",
TWStrings.toHexString(uint160(account), 20),
" is missing role ",
TWStrings.toHexString(uint256(role), 32)
)
)
);
}
}
}
文件 6 的 9:ProductMarket.sol
pragma solidity ^0.8.20;
import "./interface/IProductMarket.sol";
import "./interface/IProductToken.sol";
import "./interface/IVipManager.sol";
import "@thirdweb-dev/contracts/extension/Permissions.sol";
import "@thirdweb-dev/contracts/lib/TWAddress.sol";
contract ProductMarket is IProductMarket, Permissions {
using TWAddress for address;
bytes32 public constant FINANCE_ROLE = keccak256("FINANCE_ROLE");
bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
uint64 private constant MAX_BPS = 10_000;
address private _vipContract;
uint256 private _totalListings;
uint256 private _totalAuctions;
mapping(uint256 => Listing) private _listings;
mapping(uint256 => ProductLookup) private _productListings;
mapping(uint256 => address) private _listingContracts;
mapping(uint256 => mapping(address => uint256)) private _listingPurchases;
mapping(uint256 => Auction) private _auctions;
mapping(uint256 => ProductLookup) private _productAuctions;
mapping(uint256 => address) private _auctionContracts;
mapping(uint256 => BidHistory) private _auctionBids;
mapping(address => BidHistory) private _addressBids;
mapping(address => bool) private _withdrawalApproved;
constructor(address defaultAdmin_, address defaultToken_, address vipContract_) {
_listingContracts[0] = defaultToken_;
_auctionContracts[0] = defaultToken_;
_vipContract = vipContract_;
_setupRole(DEFAULT_ADMIN_ROLE, defaultAdmin_);
_setRoleAdmin(FINANCE_ROLE, DEFAULT_ADMIN_ROLE);
_setRoleAdmin(MANAGER_ROLE, DEFAULT_ADMIN_ROLE);
}
function setVipContract(address _vipContract_) external onlyManager {
_vipContract = _vipContract_;
}
function createListing(
ListingParams calldata _params
) external onlyManager returns (uint256 listingId) {
unchecked {
listingId = ++_totalListings;
}
Listing storage listing = _listings[listingId];
if (_params.pubStartTimestamp < _params.vipStartTimestamp)
revert ListingVipStartAfterPubStart(
_params.vipStartTimestamp,
_params.pubStartTimestamp
);
if (_params.endTimestamp <= _params.pubStartTimestamp)
revert ListingPubStartAfterEnd(
_params.pubStartTimestamp,
_params.endTimestamp
);
if (_params.quantity < _params.reserved)
revert ListingReserveExceedsQuantity(_params.reserved, _params.quantity);
listing.productId = _params.productId;
listing.enabled = _params.enabled ? 1 : 0;
listing.quantity = _params.quantity;
listing.reserved = _params.reserved;
listing.vipLimit = _params.vipLimit;
listing.pubLimit = _params.pubLimit;
listing.vipPrice = _params.vipPrice;
listing.pubPrice = _params.pubPrice;
listing.endTimestamp = _params.endTimestamp;
listing.vipStartTimestamp = _params.vipStartTimestamp;
listing.pubStartTimestamp = _params.pubStartTimestamp;
unchecked {
uint256 reverseIdx = _productListings[_params.productId].count++;
_productListings[_params.productId].id[reverseIdx] = listingId;
}
emit ListingAdded(listingId, listing);
}
function updateListing(
uint256 _listingId,
ListingParams calldata _params
) external onlyManager {
Listing storage listing = _listings[_listingId];
if (listing.productId == 0) revert ListingDoesNotExist();
if (_params.pubStartTimestamp < _params.vipStartTimestamp)
revert ListingVipStartAfterPubStart(
_params.vipStartTimestamp,
_params.pubStartTimestamp
);
if (_params.endTimestamp <= _params.pubStartTimestamp)
revert ListingPubStartAfterEnd(
_params.pubStartTimestamp,
_params.endTimestamp
);
if (_params.quantity < _params.reserved)
revert ListingReserveExceedsQuantity(_params.reserved, _params.quantity);
unchecked {
uint256 totalPurchased = listing.vipPurchased + listing.pubPurchased;
if (_params.quantity < totalPurchased)
revert ListingPurchasesExceedsQuantity(_params.quantity, totalPurchased);
if (_params.reserved < listing.resPurchased)
revert ListingPurchasesExceedsReserve(
_params.reserved,
listing.resPurchased
);
}
listing.enabled = _params.enabled ? 1 : 0;
listing.quantity = _params.quantity;
listing.reserved = _params.reserved;
listing.vipLimit = _params.vipLimit;
listing.pubLimit = _params.pubLimit;
listing.vipPrice = _params.vipPrice;
listing.pubPrice = _params.pubPrice;
listing.endTimestamp = _params.endTimestamp;
listing.vipStartTimestamp = _params.vipStartTimestamp;
listing.pubStartTimestamp = _params.pubStartTimestamp;
emit ListingUpdated(_listingId, listing);
}
function enableListing(uint256 _listingId, bool _enabled) external onlyManager {
_listings[_listingId].enabled = _enabled ? 1 : 0;
emit ListingEnabled(_listingId, _enabled);
}
function setListingContract(
uint256 _listingId,
address _tokenContract
) external onlyManager {
_listingContracts[_listingId] = _tokenContract;
emit ListingContract(_listingId, _tokenContract);
}
function setAuctionContract(
uint256 _auctionId,
address _tokenContract
) external onlyManager {
_auctionContracts[_auctionId] = _tokenContract;
emit AuctionContract(_auctionId, _tokenContract);
}
function createAuction(
AuctionParams calldata _params
) external onlyManager returns (uint256 auctionId) {
unchecked {
auctionId = ++_totalAuctions;
}
Auction storage auction = _auctions[auctionId];
if (_params.endTimestamp <= _params.startTimestamp)
revert AuctionStartAfterEnd(_params.startTimestamp, _params.endTimestamp);
if (MAX_BPS < _params.bidBufferBps) revert AuctionBufferBpsExceedsMax();
auction.productId = _params.productId;
auction.status = AuctionStatus.CREATED;
auction.startTimestamp = _params.startTimestamp;
auction.endTimestamp = _params.endTimestamp;
auction.bidBufferBps = _params.bidBufferBps;
auction.timeBufferSeconds = _params.timeBufferSeconds;
auction.minimumBidAmount = _params.minimumBidAmount;
auction.reserveBidAmount = _params.reserveBidAmount;
unchecked {
uint256 reverseIdx = _productAuctions[_params.productId].count++;
_productAuctions[_params.productId].id[reverseIdx] = auctionId;
}
emit AuctionAdded(auctionId, auction);
}
function updateAuction(
uint256 _auctionId,
AuctionParams calldata _params
) external onlyManager {
Auction storage auction = _auctions[_auctionId];
if (auction.status == AuctionStatus.UNSET) revert AuctionDoesNotExist();
if (auction.status != AuctionStatus.CREATED) revert AuctionNotActive();
if (_params.endTimestamp <= _params.startTimestamp)
revert AuctionStartAfterEnd(_params.startTimestamp, _params.endTimestamp);
if (MAX_BPS < _params.bidBufferBps) revert AuctionBufferBpsExceedsMax();
auction.startTimestamp = _params.startTimestamp;
auction.endTimestamp = _params.endTimestamp;
auction.bidBufferBps = _params.bidBufferBps;
auction.timeBufferSeconds = _params.timeBufferSeconds;
auction.minimumBidAmount = _params.minimumBidAmount;
auction.reserveBidAmount = _params.reserveBidAmount;
emit AuctionUpdated(_auctionId, auction);
}
function cancelAuction(uint256 _auctionId) external onlyManager {
Auction storage auction = _auctions[_auctionId];
if (auction.status == AuctionStatus.UNSET) revert AuctionDoesNotExist();
if (auction.status != AuctionStatus.CREATED) revert AuctionNotActive();
if (_auctionBids[_auctionId].count != 0)
revert AuctionHasBids(_auctionBids[_auctionId].count);
auction.status = AuctionStatus.CANCELLED;
emit AuctionCancelled(_auctionId);
}
function rewardAuction(
uint256 _auctionId,
bool _allowUnmetReserve
) external onlyManager {
Auction storage auction = _auctions[_auctionId];
if (auction.status == AuctionStatus.UNSET) revert AuctionDoesNotExist();
if (auction.status != AuctionStatus.CREATED) revert AuctionNotActive();
if (block.timestamp < auction.endTimestamp)
revert AuctionNotEnded(auction.endTimestamp, block.timestamp);
uint256 numberOfBids = _auctionBids[_auctionId].count;
if (numberOfBids == 0) revert AuctionHasNoBids();
Bid memory winningBid = _auctionBids[_auctionId].bids[numberOfBids - 1];
if (winningBid.bidAmount < auction.reserveBidAmount && !_allowUnmetReserve)
revert AuctionReserveNotMet(winningBid.bidAmount, auction.reserveBidAmount);
auction.status = AuctionStatus.COMPLETED;
IProductToken(getAuctionContract(_auctionId)).mintTo(
winningBid.bidder,
auction.productId
);
emit AuctionClosed(
_auctionId,
winningBid.bidder,
winningBid.bidAmount,
auction.productId,
true,
false
);
}
function closeAuction(uint256 _auctionId) external onlyManager {
Auction storage auction = _auctions[_auctionId];
if (auction.status == AuctionStatus.UNSET) revert AuctionDoesNotExist();
if (auction.status != AuctionStatus.CREATED) revert AuctionNotActive();
if (block.timestamp < auction.endTimestamp)
revert AuctionNotEnded(auction.endTimestamp, block.timestamp);
uint256 numberOfBids = _auctionBids[_auctionId].count;
if (numberOfBids == 0) revert AuctionHasNoBids();
Bid memory winningBid = _auctionBids[_auctionId].bids[numberOfBids - 1];
if (auction.reserveBidAmount <= winningBid.bidAmount)
revert AuctionReserveWasMet(winningBid.bidAmount, auction.reserveBidAmount);
auction.status = AuctionStatus.COMPLETED;
(bool success, ) = winningBid.bidder.call{value: winningBid.bidAmount}("");
if (!success) revert AuctionPreviousBidRefundRejected();
emit AuctionClosed(
_auctionId,
winningBid.bidder,
winningBid.bidAmount,
auction.productId,
false,
true
);
}
function approveWithdrawalRecipient(
address _recipient,
bool _approved
) external onlyFinance {
_withdrawalApproved[_recipient] = _approved;
emit WithdrawalRecipientApproved(_recipient, _approved);
}
function withdrawIncome(
address payable _recipient,
uint256 _amount
) external onlyFinance {
if (address(this).balance < _amount)
revert WithdrawalInsufficientBalance(_amount, address(this).balance);
if (!_withdrawalApproved[_recipient]) revert WithdrawalRecipientNotApproved();
(bool success, ) = _recipient.call{value: _amount}("");
if (!success) revert WithdrawalRecipientRejectedTransfer();
emit IncomeWithdrawal(msg.sender, _recipient, _amount);
}
function buyFromListing(
uint256 _listingId,
address _buyFor,
uint256 _quantity,
uint256 _expectedTotalPrice
) external payable {
Listing storage listing = _listings[_listingId];
if (listing.productId == 0) revert ListingDoesNotExist();
if (listing.enabled == 0) revert ListingNotEnabled();
if (_expectedTotalPrice != msg.value)
revert ListingExpectedPriceNotEqualValue(_expectedTotalPrice, msg.value);
if (listing.endTimestamp < block.timestamp) revert ListingHasEnded();
unchecked {
uint256 availableQuantity = listing.quantity -
(listing.vipPurchased + listing.pubPurchased);
if (availableQuantity < _quantity)
revert ListingInsufficientQuantity(_quantity, availableQuantity);
}
uint256 listingPurchases = _listingPurchases[_listingId][msg.sender] + _quantity;
if (_checkListingVip(_listingId, msg.sender)) {
if (block.timestamp < listing.vipStartTimestamp)
revert ListingVipSaleNotStarted(
listing.vipStartTimestamp,
block.timestamp
);
if (listing.vipLimit < listingPurchases)
revert ListingVipLimitExceeded(listingPurchases, listing.vipLimit);
uint256 actualTotalPrice = listing.vipPrice * _quantity;
if (actualTotalPrice != _expectedTotalPrice)
revert ListingVipExpectedPriceInvalid(
_expectedTotalPrice,
actualTotalPrice
);
unchecked {
if (block.timestamp < listing.pubStartTimestamp) {
uint256 reserveAvailable = listing.reserved - listing.resPurchased;
if (reserveAvailable < _quantity)
revert ListingVipReserveExceeded(_quantity, reserveAvailable);
listing.resPurchased += uint16(_quantity);
}
listing.vipPurchased += uint16(_quantity);
listing.vipIncome += uint72(_expectedTotalPrice);
}
} else {
if (block.timestamp < listing.pubStartTimestamp)
revert ListingPublicSaleNotStarted(
listing.pubStartTimestamp,
block.timestamp
);
if (listing.pubLimit < listingPurchases)
revert ListingPublicLimitExceeded(listingPurchases, listing.pubLimit);
uint256 actualTotalPrice = listing.pubPrice * _quantity;
if (actualTotalPrice != _expectedTotalPrice)
revert ListingPublicExpectedPriceInvalid(
_expectedTotalPrice,
actualTotalPrice
);
unchecked {
listing.pubPurchased += uint16(_quantity);
listing.pubIncome += uint72(_expectedTotalPrice);
}
}
_listingPurchases[_listingId][msg.sender] = listingPurchases;
IProductToken(getListingContract(_listingId)).batchMintTo(
_buyFor,
listing.productId,
_quantity
);
emit NewSale(
_listingId,
msg.sender,
_buyFor,
listing.productId,
_quantity,
_expectedTotalPrice
);
}
function bidInAuction(uint256 _auctionId, uint256 _bidAmount) external payable {
Auction memory auction = _auctions[_auctionId];
if (auction.status == AuctionStatus.UNSET) revert AuctionDoesNotExist();
if (auction.status != AuctionStatus.CREATED) revert AuctionNotActive();
if (block.timestamp < auction.startTimestamp)
revert AuctionNotStarted(auction.startTimestamp, block.timestamp);
if (auction.endTimestamp < block.timestamp) revert AuctionHasEnded();
if (_bidAmount == 0) revert AuctionBidAmountZero();
if (_bidAmount < auction.minimumBidAmount)
revert AuctionBidBelowMinimum(_bidAmount, auction.minimumBidAmount);
if (_bidAmount != msg.value)
revert AuctionBidAmountNotEqualValue(_bidAmount, msg.value);
uint256 numberOfBids = _auctionBids[_auctionId].count;
if (numberOfBids > 0) {
Bid memory previousBid = _auctionBids[_auctionId].bids[numberOfBids - 1];
unchecked {
uint256 requiredBidAmount = previousBid.bidAmount +
((previousBid.bidAmount * auction.bidBufferBps) / MAX_BPS);
if (_bidAmount < requiredBidAmount)
revert AuctionBidAmountInsufficient(_bidAmount, requiredBidAmount);
}
(bool success, ) = previousBid.bidder.call{value: previousBid.bidAmount}("");
if (!success) revert AuctionPreviousBidRefundRejected();
if (_auctionBids[_auctionId].count != numberOfBids) revert();
}
unchecked {
++_auctionBids[_auctionId].count;
}
Bid memory newBid = Bid({
auctionId: uint64(_auctionId),
bidTimestamp: uint32(block.timestamp),
bidder: msg.sender,
bidAmount: _bidAmount
});
_auctionBids[_auctionId].bids[numberOfBids] = newBid;
unchecked {
uint256 addressBids = _addressBids[msg.sender].count++;
_addressBids[msg.sender].bids[addressBids] = newBid;
}
if (auction.endTimestamp - block.timestamp <= auction.timeBufferSeconds) {
unchecked {
auction.endTimestamp += uint32(auction.timeBufferSeconds);
}
_auctions[_auctionId] = auction;
}
emit NewBid(_auctionId, msg.sender, _bidAmount, auction);
}
function getVipContract() external view returns (address) {
return _vipContract;
}
function totalListings() external view returns (uint256) {
return _totalListings;
}
function getListingContract(uint256 _listingId) public view returns (address) {
if (_listingContracts[_listingId] == address(0)) {
return _listingContracts[0];
} else {
return _listingContracts[_listingId];
}
}
function getListing(
uint256 _listingId
) external view returns (ListingQuery memory _listing) {
return ListingQuery({listingId: _listingId, listingData: _listings[_listingId]});
}
function getAllProductListings(
uint256 _productId
) external view returns (ListingQuery[] memory _allListings) {
ProductLookup storage productLookup = _productListings[_productId];
uint256 count = productLookup.count;
_allListings = new ListingQuery[](count);
for (uint256 i; i < count; ) {
uint256 listingId = productLookup.id[i];
_allListings[i] = ListingQuery({
listingId: listingId,
listingData: _listings[listingId]
});
unchecked {
++i;
}
}
}
function getAllListings(
uint256 _startId,
uint256 _endId
) external view returns (ListingQuery[] memory _allListings) {
if (_startId == 0 || _endId < _startId) revert ListingQueryInvalidRange();
unchecked {
uint256 maxId = (_endId > _totalListings ? _totalListings : _endId) + 1;
_allListings = new ListingQuery[](maxId - _startId);
for (uint256 i = _startId; i < maxId; ) {
_allListings[i - _startId] = ListingQuery({
listingId: i,
listingData: _listings[i]
});
++i;
}
}
}
function getWithdrawalApproved(address _recipient) external view returns (bool) {
return _withdrawalApproved[_recipient];
}
function totalAuctions() external view returns (uint256) {
return _totalAuctions;
}
function getAuctionContract(uint256 _auctionId) public view returns (address) {
if (_auctionContracts[_auctionId] == address(0)) {
return _auctionContracts[0];
} else {
return _auctionContracts[_auctionId];
}
}
function getAuction(
uint256 _auctionId
) external view returns (AuctionQuery memory _auction) {
unchecked {
uint256 numberOfBids = _auctionBids[_auctionId].count;
return
AuctionQuery({
auctionId: _auctionId,
auctionData: _auctions[_auctionId],
winningBid: _auctionBids[_auctionId].bids[
numberOfBids > 0 ? numberOfBids - 1 : 0
]
});
}
}
function getAllProductAuctions(
uint256 _productId
) external view returns (AuctionQuery[] memory _allAuctions) {
ProductLookup storage productLookup = _productAuctions[_productId];
uint256 count = productLookup.count;
_allAuctions = new AuctionQuery[](count);
for (uint256 i; i < count; ) {
uint256 auctionId = productLookup.id[i];
uint256 numberOfBids = _auctionBids[i].count;
unchecked {
_allAuctions[i] = AuctionQuery({
auctionId: auctionId,
auctionData: _auctions[auctionId],
winningBid: _auctionBids[auctionId].bids[
numberOfBids > 0 ? numberOfBids - 1 : 0
]
});
++i;
}
}
}
function getAllAuctions(
uint256 _startId,
uint256 _endId
) external view returns (AuctionQuery[] memory _allAuctions) {
if (_startId == 0 || _endId < _startId) revert AuctionQueryInvalidRange();
unchecked {
uint256 maxId = (_endId > _totalAuctions ? _totalAuctions : _endId) + 1;
_allAuctions = new AuctionQuery[](maxId - _startId);
for (uint256 i = _startId; i < maxId; ) {
uint256 numberOfBids = _auctionBids[i].count;
_allAuctions[i - _startId] = AuctionQuery({
auctionId: i,
auctionData: _auctions[i],
winningBid: _auctionBids[i].bids[
numberOfBids > 0 ? numberOfBids - 1 : 0
]
});
++i;
}
}
}
function getAuctionBids(
uint256 _auctionId
) external view returns (Bid[] memory _bids) {
uint256 numberOfBids = _auctionBids[_auctionId].count;
_bids = new Bid[](numberOfBids);
for (uint256 i; i < numberOfBids; ) {
_bids[i] = _auctionBids[_auctionId].bids[i];
unchecked {
++i;
}
}
}
function getAddressBids(address _bidder) external view returns (Bid[] memory _bids) {
uint256 numberOfBids = _addressBids[_bidder].count;
_bids = new Bid[](numberOfBids);
for (uint256 i; i < numberOfBids; ) {
_bids[i] = _addressBids[_bidder].bids[i];
unchecked {
++i;
}
}
}
function getWinningBidAmount(uint256 _auctionId) external view returns (uint256) {
Auction memory auction = _auctions[_auctionId];
if (auction.status == AuctionStatus.UNSET) revert AuctionDoesNotExist();
uint256 numberOfBids = _auctionBids[_auctionId].count;
if (numberOfBids > 0) {
unchecked {
Bid memory previousBid = _auctionBids[_auctionId].bids[numberOfBids - 1];
return
previousBid.bidAmount +
((previousBid.bidAmount * auction.bidBufferBps) / MAX_BPS);
}
}
return auction.minimumBidAmount;
}
modifier onlyFinance() {
_checkFinanceAdmin();
_;
}
modifier onlyManager() {
_checkManagerAdmin();
_;
}
function _checkFinanceAdmin() internal view {
if (
!hasRole(DEFAULT_ADMIN_ROLE, msg.sender) && !hasRole(FINANCE_ROLE, msg.sender)
) {
revert FinanceRoleRequired();
}
}
function _checkManagerAdmin() internal view {
if (
!hasRole(DEFAULT_ADMIN_ROLE, msg.sender) && !hasRole(MANAGER_ROLE, msg.sender)
) {
revert ManagerRoleRequired();
}
}
function _checkListingVip(
uint256 _listingId,
address _member
) internal view returns (bool) {
if (_vipContract != address(0))
return IVipManager(_vipContract).isVip(_listingId, _member);
return false;
}
}
文件 7 的 9:SykyMarket.sol
pragma solidity ^0.8.20;
import "../base/ProductMarket.sol";
contract SykyMarket is ProductMarket {
string public constant ENV = "MAINNET";
string public constant VER = "1.0.1";
constructor(
address defaultAdmin_,
address defaultToken_,
address vipContract_
) ProductMarket(defaultAdmin_, defaultToken_, vipContract_) {}
}
文件 8 的 9:TWAddress.sol
pragma solidity ^0.8.0;
library TWAddress {
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);
}
}
}
}
文件 9 的 9:TWStrings.sol
pragma solidity ^0.8.0;
library TWStrings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
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);
}
}
{
"compilationTarget": {
"contracts/syky/SykyMarket.sol": "SykyMarket"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 300
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"defaultAdmin_","type":"address"},{"internalType":"address","name":"defaultToken_","type":"address"},{"internalType":"address","name":"vipContract_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"bidAmount","type":"uint256"},{"internalType":"uint256","name":"requiredBidAmount","type":"uint256"}],"name":"AuctionBidAmountInsufficient","type":"error"},{"inputs":[{"internalType":"uint256","name":"bidAmount","type":"uint256"},{"internalType":"uint256","name":"transactionValue","type":"uint256"}],"name":"AuctionBidAmountNotEqualValue","type":"error"},{"inputs":[],"name":"AuctionBidAmountZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"bidAmount","type":"uint256"},{"internalType":"uint256","name":"minimumBidAmount","type":"uint256"}],"name":"AuctionBidBelowMinimum","type":"error"},{"inputs":[],"name":"AuctionBufferBpsExceedsMax","type":"error"},{"inputs":[],"name":"AuctionDoesNotExist","type":"error"},{"inputs":[{"internalType":"uint256","name":"numberOfBids","type":"uint256"}],"name":"AuctionHasBids","type":"error"},{"inputs":[],"name":"AuctionHasEnded","type":"error"},{"inputs":[],"name":"AuctionHasNoBids","type":"error"},{"inputs":[],"name":"AuctionNotActive","type":"error"},{"inputs":[{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint256","name":"currentTimestamp","type":"uint256"}],"name":"AuctionNotEnded","type":"error"},{"inputs":[{"internalType":"uint32","name":"startTimestamp","type":"uint32"},{"internalType":"uint256","name":"currentTimestamp","type":"uint256"}],"name":"AuctionNotStarted","type":"error"},{"inputs":[],"name":"AuctionPreviousBidRefundRejected","type":"error"},{"inputs":[],"name":"AuctionQueryInvalidRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"highestBidAmount","type":"uint256"},{"internalType":"uint256","name":"reserveBidAmount","type":"uint256"}],"name":"AuctionReserveNotMet","type":"error"},{"inputs":[{"internalType":"uint256","name":"highestBidAmount","type":"uint256"},{"internalType":"uint256","name":"reserveBidAmount","type":"uint256"}],"name":"AuctionReserveWasMet","type":"error"},{"inputs":[{"internalType":"uint32","name":"startTimestamp","type":"uint32"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"}],"name":"AuctionStartAfterEnd","type":"error"},{"inputs":[],"name":"FinanceRoleRequired","type":"error"},{"inputs":[],"name":"ListingDoesNotExist","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedTotalPrice","type":"uint256"},{"internalType":"uint256","name":"transactionValue","type":"uint256"}],"name":"ListingExpectedPriceNotEqualValue","type":"error"},{"inputs":[],"name":"ListingHasEnded","type":"error"},{"inputs":[{"internalType":"uint256","name":"requestedQuantity","type":"uint256"},{"internalType":"uint256","name":"availableQuantity","type":"uint256"}],"name":"ListingInsufficientQuantity","type":"error"},{"inputs":[],"name":"ListingNotEnabled","type":"error"},{"inputs":[{"internalType":"uint32","name":"pubStartTimestamp","type":"uint32"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"}],"name":"ListingPubStartAfterEnd","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedTotalPrice","type":"uint256"},{"internalType":"uint256","name":"actualTotalPrice","type":"uint256"}],"name":"ListingPublicExpectedPriceInvalid","type":"error"},{"inputs":[{"internalType":"uint256","name":"purchases","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"ListingPublicLimitExceeded","type":"error"},{"inputs":[{"internalType":"uint64","name":"publicStartTime","type":"uint64"},{"internalType":"uint256","name":"currentTimestamp","type":"uint256"}],"name":"ListingPublicSaleNotStarted","type":"error"},{"inputs":[{"internalType":"uint16","name":"quantity","type":"uint16"},{"internalType":"uint256","name":"purchased","type":"uint256"}],"name":"ListingPurchasesExceedsQuantity","type":"error"},{"inputs":[{"internalType":"uint16","name":"reserve","type":"uint16"},{"internalType":"uint256","name":"purchased","type":"uint256"}],"name":"ListingPurchasesExceedsReserve","type":"error"},{"inputs":[],"name":"ListingQueryInvalidRange","type":"error"},{"inputs":[{"internalType":"uint16","name":"reserved","type":"uint16"},{"internalType":"uint16","name":"quantity","type":"uint16"}],"name":"ListingReserveExceedsQuantity","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedTotalPrice","type":"uint256"},{"internalType":"uint256","name":"actualTotalPrice","type":"uint256"}],"name":"ListingVipExpectedPriceInvalid","type":"error"},{"inputs":[{"internalType":"uint256","name":"purchases","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"ListingVipLimitExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"requestedQuantity","type":"uint256"},{"internalType":"uint256","name":"availableQuantity","type":"uint256"}],"name":"ListingVipReserveExceeded","type":"error"},{"inputs":[{"internalType":"uint64","name":"vipStartTime","type":"uint64"},{"internalType":"uint256","name":"currentTimestamp","type":"uint256"}],"name":"ListingVipSaleNotStarted","type":"error"},{"inputs":[{"internalType":"uint32","name":"vipStartTimestamp","type":"uint32"},{"internalType":"uint32","name":"pubStartTimestamp","type":"uint32"}],"name":"ListingVipStartAfterPubStart","type":"error"},{"inputs":[],"name":"ManagerRoleRequired","type":"error"},{"inputs":[{"internalType":"uint256","name":"requested","type":"uint256"},{"internalType":"uint256","name":"available","type":"uint256"}],"name":"WithdrawalInsufficientBalance","type":"error"},{"inputs":[],"name":"WithdrawalRecipientNotApproved","type":"error"},{"inputs":[],"name":"WithdrawalRecipientRejectedTransfer","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"components":[{"internalType":"uint56","name":"productId","type":"uint56"},{"internalType":"enum IProductMarket.AuctionStatus","name":"status","type":"uint8"},{"internalType":"uint32","name":"startTimestamp","type":"uint32"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint64","name":"bidBufferBps","type":"uint64"},{"internalType":"uint64","name":"timeBufferSeconds","type":"uint64"},{"internalType":"uint256","name":"minimumBidAmount","type":"uint256"},{"internalType":"uint256","name":"reserveBidAmount","type":"uint256"}],"indexed":false,"internalType":"struct IProductMarket.Auction","name":"auction","type":"tuple"}],"name":"AuctionAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"AuctionCancelled","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":"bidAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"productId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"tokenAwarded","type":"bool"},{"indexed":false,"internalType":"bool","name":"bidRefunded","type":"bool"}],"name":"AuctionClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tokenContract","type":"address"}],"name":"AuctionContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"components":[{"internalType":"uint56","name":"productId","type":"uint56"},{"internalType":"enum IProductMarket.AuctionStatus","name":"status","type":"uint8"},{"internalType":"uint32","name":"startTimestamp","type":"uint32"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint64","name":"bidBufferBps","type":"uint64"},{"internalType":"uint64","name":"timeBufferSeconds","type":"uint64"},{"internalType":"uint256","name":"minimumBidAmount","type":"uint256"},{"internalType":"uint256","name":"reserveBidAmount","type":"uint256"}],"indexed":false,"internalType":"struct IProductMarket.Auction","name":"auction","type":"tuple"}],"name":"AuctionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"IncomeWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"listingId","type":"uint256"},{"components":[{"internalType":"uint24","name":"productId","type":"uint24"},{"internalType":"uint8","name":"enabled","type":"uint8"},{"internalType":"uint16","name":"quantity","type":"uint16"},{"internalType":"uint16","name":"reserved","type":"uint16"},{"internalType":"uint16","name":"vipLimit","type":"uint16"},{"internalType":"uint16","name":"pubLimit","type":"uint16"},{"internalType":"uint64","name":"vipPrice","type":"uint64"},{"internalType":"uint64","name":"pubPrice","type":"uint64"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint32","name":"vipStartTimestamp","type":"uint32"},{"internalType":"uint32","name":"pubStartTimestamp","type":"uint32"},{"internalType":"uint16","name":"resPurchased","type":"uint16"},{"internalType":"uint16","name":"vipPurchased","type":"uint16"},{"internalType":"uint16","name":"pubPurchased","type":"uint16"},{"internalType":"uint72","name":"vipIncome","type":"uint72"},{"internalType":"uint72","name":"pubIncome","type":"uint72"}],"indexed":false,"internalType":"struct IProductMarket.Listing","name":"listing","type":"tuple"}],"name":"ListingAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"listingId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tokenContract","type":"address"}],"name":"ListingContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"listingId","type":"uint256"},{"indexed":true,"internalType":"bool","name":"enabled","type":"bool"}],"name":"ListingEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"listingId","type":"uint256"},{"components":[{"internalType":"uint24","name":"productId","type":"uint24"},{"internalType":"uint8","name":"enabled","type":"uint8"},{"internalType":"uint16","name":"quantity","type":"uint16"},{"internalType":"uint16","name":"reserved","type":"uint16"},{"internalType":"uint16","name":"vipLimit","type":"uint16"},{"internalType":"uint16","name":"pubLimit","type":"uint16"},{"internalType":"uint64","name":"vipPrice","type":"uint64"},{"internalType":"uint64","name":"pubPrice","type":"uint64"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint32","name":"vipStartTimestamp","type":"uint32"},{"internalType":"uint32","name":"pubStartTimestamp","type":"uint32"},{"internalType":"uint16","name":"resPurchased","type":"uint16"},{"internalType":"uint16","name":"vipPurchased","type":"uint16"},{"internalType":"uint16","name":"pubPurchased","type":"uint16"},{"internalType":"uint72","name":"vipIncome","type":"uint72"},{"internalType":"uint72","name":"pubIncome","type":"uint72"}],"indexed":false,"internalType":"struct IProductMarket.Listing","name":"listing","type":"tuple"}],"name":"ListingUpdated","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":"bidAmount","type":"uint256"},{"components":[{"internalType":"uint56","name":"productId","type":"uint56"},{"internalType":"enum IProductMarket.AuctionStatus","name":"status","type":"uint8"},{"internalType":"uint32","name":"startTimestamp","type":"uint32"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint64","name":"bidBufferBps","type":"uint64"},{"internalType":"uint64","name":"timeBufferSeconds","type":"uint64"},{"internalType":"uint256","name":"minimumBidAmount","type":"uint256"},{"internalType":"uint256","name":"reserveBidAmount","type":"uint256"}],"indexed":false,"internalType":"struct IProductMarket.Auction","name":"auction","type":"tuple"}],"name":"NewBid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"listingId","type":"uint256"},{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"productId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"NewSale","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"bool","name":"approved","type":"bool"}],"name":"WithdrawalRecipientApproved","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ENV","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINANCE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VER","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"approveWithdrawalRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_auctionId","type":"uint256"},{"internalType":"uint256","name":"_bidAmount","type":"uint256"}],"name":"bidInAuction","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_listingId","type":"uint256"},{"internalType":"address","name":"_buyFor","type":"address"},{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"uint256","name":"_expectedTotalPrice","type":"uint256"}],"name":"buyFromListing","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_auctionId","type":"uint256"}],"name":"cancelAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_auctionId","type":"uint256"}],"name":"closeAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint56","name":"productId","type":"uint56"},{"internalType":"uint32","name":"startTimestamp","type":"uint32"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint64","name":"bidBufferBps","type":"uint64"},{"internalType":"uint64","name":"timeBufferSeconds","type":"uint64"},{"internalType":"uint256","name":"minimumBidAmount","type":"uint256"},{"internalType":"uint256","name":"reserveBidAmount","type":"uint256"}],"internalType":"struct IProductMarket.AuctionParams","name":"_params","type":"tuple"}],"name":"createAuction","outputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint24","name":"productId","type":"uint24"},{"internalType":"uint16","name":"quantity","type":"uint16"},{"internalType":"uint16","name":"reserved","type":"uint16"},{"internalType":"uint16","name":"vipLimit","type":"uint16"},{"internalType":"uint16","name":"pubLimit","type":"uint16"},{"internalType":"uint64","name":"vipPrice","type":"uint64"},{"internalType":"uint64","name":"pubPrice","type":"uint64"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint32","name":"vipStartTimestamp","type":"uint32"},{"internalType":"uint32","name":"pubStartTimestamp","type":"uint32"},{"internalType":"bool","name":"enabled","type":"bool"}],"internalType":"struct IProductMarket.ListingParams","name":"_params","type":"tuple"}],"name":"createListing","outputs":[{"internalType":"uint256","name":"listingId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_listingId","type":"uint256"},{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"enableListing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bidder","type":"address"}],"name":"getAddressBids","outputs":[{"components":[{"internalType":"uint64","name":"auctionId","type":"uint64"},{"internalType":"uint32","name":"bidTimestamp","type":"uint32"},{"internalType":"address","name":"bidder","type":"address"},{"internalType":"uint256","name":"bidAmount","type":"uint256"}],"internalType":"struct IProductMarket.Bid[]","name":"_bids","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_startId","type":"uint256"},{"internalType":"uint256","name":"_endId","type":"uint256"}],"name":"getAllAuctions","outputs":[{"components":[{"internalType":"uint256","name":"auctionId","type":"uint256"},{"components":[{"internalType":"uint56","name":"productId","type":"uint56"},{"internalType":"enum IProductMarket.AuctionStatus","name":"status","type":"uint8"},{"internalType":"uint32","name":"startTimestamp","type":"uint32"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint64","name":"bidBufferBps","type":"uint64"},{"internalType":"uint64","name":"timeBufferSeconds","type":"uint64"},{"internalType":"uint256","name":"minimumBidAmount","type":"uint256"},{"internalType":"uint256","name":"reserveBidAmount","type":"uint256"}],"internalType":"struct IProductMarket.Auction","name":"auctionData","type":"tuple"},{"components":[{"internalType":"uint64","name":"auctionId","type":"uint64"},{"internalType":"uint32","name":"bidTimestamp","type":"uint32"},{"internalType":"address","name":"bidder","type":"address"},{"internalType":"uint256","name":"bidAmount","type":"uint256"}],"internalType":"struct IProductMarket.Bid","name":"winningBid","type":"tuple"}],"internalType":"struct IProductMarket.AuctionQuery[]","name":"_allAuctions","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_startId","type":"uint256"},{"internalType":"uint256","name":"_endId","type":"uint256"}],"name":"getAllListings","outputs":[{"components":[{"internalType":"uint256","name":"listingId","type":"uint256"},{"components":[{"internalType":"uint24","name":"productId","type":"uint24"},{"internalType":"uint8","name":"enabled","type":"uint8"},{"internalType":"uint16","name":"quantity","type":"uint16"},{"internalType":"uint16","name":"reserved","type":"uint16"},{"internalType":"uint16","name":"vipLimit","type":"uint16"},{"internalType":"uint16","name":"pubLimit","type":"uint16"},{"internalType":"uint64","name":"vipPrice","type":"uint64"},{"internalType":"uint64","name":"pubPrice","type":"uint64"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint32","name":"vipStartTimestamp","type":"uint32"},{"internalType":"uint32","name":"pubStartTimestamp","type":"uint32"},{"internalType":"uint16","name":"resPurchased","type":"uint16"},{"internalType":"uint16","name":"vipPurchased","type":"uint16"},{"internalType":"uint16","name":"pubPurchased","type":"uint16"},{"internalType":"uint72","name":"vipIncome","type":"uint72"},{"internalType":"uint72","name":"pubIncome","type":"uint72"}],"internalType":"struct IProductMarket.Listing","name":"listingData","type":"tuple"}],"internalType":"struct IProductMarket.ListingQuery[]","name":"_allListings","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_productId","type":"uint256"}],"name":"getAllProductAuctions","outputs":[{"components":[{"internalType":"uint256","name":"auctionId","type":"uint256"},{"components":[{"internalType":"uint56","name":"productId","type":"uint56"},{"internalType":"enum IProductMarket.AuctionStatus","name":"status","type":"uint8"},{"internalType":"uint32","name":"startTimestamp","type":"uint32"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint64","name":"bidBufferBps","type":"uint64"},{"internalType":"uint64","name":"timeBufferSeconds","type":"uint64"},{"internalType":"uint256","name":"minimumBidAmount","type":"uint256"},{"internalType":"uint256","name":"reserveBidAmount","type":"uint256"}],"internalType":"struct IProductMarket.Auction","name":"auctionData","type":"tuple"},{"components":[{"internalType":"uint64","name":"auctionId","type":"uint64"},{"internalType":"uint32","name":"bidTimestamp","type":"uint32"},{"internalType":"address","name":"bidder","type":"address"},{"internalType":"uint256","name":"bidAmount","type":"uint256"}],"internalType":"struct IProductMarket.Bid","name":"winningBid","type":"tuple"}],"internalType":"struct IProductMarket.AuctionQuery[]","name":"_allAuctions","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_productId","type":"uint256"}],"name":"getAllProductListings","outputs":[{"components":[{"internalType":"uint256","name":"listingId","type":"uint256"},{"components":[{"internalType":"uint24","name":"productId","type":"uint24"},{"internalType":"uint8","name":"enabled","type":"uint8"},{"internalType":"uint16","name":"quantity","type":"uint16"},{"internalType":"uint16","name":"reserved","type":"uint16"},{"internalType":"uint16","name":"vipLimit","type":"uint16"},{"internalType":"uint16","name":"pubLimit","type":"uint16"},{"internalType":"uint64","name":"vipPrice","type":"uint64"},{"internalType":"uint64","name":"pubPrice","type":"uint64"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint32","name":"vipStartTimestamp","type":"uint32"},{"internalType":"uint32","name":"pubStartTimestamp","type":"uint32"},{"internalType":"uint16","name":"resPurchased","type":"uint16"},{"internalType":"uint16","name":"vipPurchased","type":"uint16"},{"internalType":"uint16","name":"pubPurchased","type":"uint16"},{"internalType":"uint72","name":"vipIncome","type":"uint72"},{"internalType":"uint72","name":"pubIncome","type":"uint72"}],"internalType":"struct IProductMarket.Listing","name":"listingData","type":"tuple"}],"internalType":"struct IProductMarket.ListingQuery[]","name":"_allListings","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_auctionId","type":"uint256"}],"name":"getAuction","outputs":[{"components":[{"internalType":"uint256","name":"auctionId","type":"uint256"},{"components":[{"internalType":"uint56","name":"productId","type":"uint56"},{"internalType":"enum IProductMarket.AuctionStatus","name":"status","type":"uint8"},{"internalType":"uint32","name":"startTimestamp","type":"uint32"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint64","name":"bidBufferBps","type":"uint64"},{"internalType":"uint64","name":"timeBufferSeconds","type":"uint64"},{"internalType":"uint256","name":"minimumBidAmount","type":"uint256"},{"internalType":"uint256","name":"reserveBidAmount","type":"uint256"}],"internalType":"struct IProductMarket.Auction","name":"auctionData","type":"tuple"},{"components":[{"internalType":"uint64","name":"auctionId","type":"uint64"},{"internalType":"uint32","name":"bidTimestamp","type":"uint32"},{"internalType":"address","name":"bidder","type":"address"},{"internalType":"uint256","name":"bidAmount","type":"uint256"}],"internalType":"struct IProductMarket.Bid","name":"winningBid","type":"tuple"}],"internalType":"struct IProductMarket.AuctionQuery","name":"_auction","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_auctionId","type":"uint256"}],"name":"getAuctionBids","outputs":[{"components":[{"internalType":"uint64","name":"auctionId","type":"uint64"},{"internalType":"uint32","name":"bidTimestamp","type":"uint32"},{"internalType":"address","name":"bidder","type":"address"},{"internalType":"uint256","name":"bidAmount","type":"uint256"}],"internalType":"struct IProductMarket.Bid[]","name":"_bids","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_auctionId","type":"uint256"}],"name":"getAuctionContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_listingId","type":"uint256"}],"name":"getListing","outputs":[{"components":[{"internalType":"uint256","name":"listingId","type":"uint256"},{"components":[{"internalType":"uint24","name":"productId","type":"uint24"},{"internalType":"uint8","name":"enabled","type":"uint8"},{"internalType":"uint16","name":"quantity","type":"uint16"},{"internalType":"uint16","name":"reserved","type":"uint16"},{"internalType":"uint16","name":"vipLimit","type":"uint16"},{"internalType":"uint16","name":"pubLimit","type":"uint16"},{"internalType":"uint64","name":"vipPrice","type":"uint64"},{"internalType":"uint64","name":"pubPrice","type":"uint64"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint32","name":"vipStartTimestamp","type":"uint32"},{"internalType":"uint32","name":"pubStartTimestamp","type":"uint32"},{"internalType":"uint16","name":"resPurchased","type":"uint16"},{"internalType":"uint16","name":"vipPurchased","type":"uint16"},{"internalType":"uint16","name":"pubPurchased","type":"uint16"},{"internalType":"uint72","name":"vipIncome","type":"uint72"},{"internalType":"uint72","name":"pubIncome","type":"uint72"}],"internalType":"struct IProductMarket.Listing","name":"listingData","type":"tuple"}],"internalType":"struct IProductMarket.ListingQuery","name":"_listing","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_listingId","type":"uint256"}],"name":"getListingContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVipContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_auctionId","type":"uint256"}],"name":"getWinningBidAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"}],"name":"getWithdrawalApproved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRoleWithSwitch","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_auctionId","type":"uint256"},{"internalType":"bool","name":"_allowUnmetReserve","type":"bool"}],"name":"rewardAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_auctionId","type":"uint256"},{"internalType":"address","name":"_tokenContract","type":"address"}],"name":"setAuctionContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_listingId","type":"uint256"},{"internalType":"address","name":"_tokenContract","type":"address"}],"name":"setListingContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vipContract_","type":"address"}],"name":"setVipContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalAuctions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalListings","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_auctionId","type":"uint256"},{"components":[{"internalType":"uint56","name":"productId","type":"uint56"},{"internalType":"uint32","name":"startTimestamp","type":"uint32"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint64","name":"bidBufferBps","type":"uint64"},{"internalType":"uint64","name":"timeBufferSeconds","type":"uint64"},{"internalType":"uint256","name":"minimumBidAmount","type":"uint256"},{"internalType":"uint256","name":"reserveBidAmount","type":"uint256"}],"internalType":"struct IProductMarket.AuctionParams","name":"_params","type":"tuple"}],"name":"updateAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_listingId","type":"uint256"},{"components":[{"internalType":"uint24","name":"productId","type":"uint24"},{"internalType":"uint16","name":"quantity","type":"uint16"},{"internalType":"uint16","name":"reserved","type":"uint16"},{"internalType":"uint16","name":"vipLimit","type":"uint16"},{"internalType":"uint16","name":"pubLimit","type":"uint16"},{"internalType":"uint64","name":"vipPrice","type":"uint64"},{"internalType":"uint64","name":"pubPrice","type":"uint64"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint32","name":"vipStartTimestamp","type":"uint32"},{"internalType":"uint32","name":"pubStartTimestamp","type":"uint32"},{"internalType":"bool","name":"enabled","type":"bool"}],"internalType":"struct IProductMarket.ListingParams","name":"_params","type":"tuple"}],"name":"updateListing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawIncome","outputs":[],"stateMutability":"nonpayable","type":"function"}]