// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `address` (`addressSet`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/libraryAddressSet{
// To implement this library for multiple types with as little code// repetition as possible, we write it in terms of a generic Set type with// address values.// The Set implementation uses private functions, and user-facing// implementations (such as AddressSet) are just wrappers around the// underlying Set.// This means that we can only create new EnumerableSets for types that fit// in address.structSet {
// Storage of set valuesaddress[] _values;
// Position of the value in the `values` array, plus 1 because index 0// means a value is not in the set.mapping(address=>uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/functionadd(Set storage set, address value) internalreturns (bool) {
if (!contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
returntrue;
} else {
returnfalse;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/functionremove(Set storage set, address value) internalreturns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slotuint256 valueIndex = set._indexes[value];
if (valueIndex !=0) {
// Equivalent to contains(set, value)// To delete an element from the _values array in O(1), we swap the element to delete with the last one in// the array, and then remove the last element (sometimes called as 'swap and pop').// This modifies the order of the array, as noted in {at}.uint256 toDeleteIndex = valueIndex -1;
uint256 lastIndex = set._values.length-1;
if (lastIndex != toDeleteIndex) {
address lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slotdelete set._indexes[value];
returntrue;
} else {
returnfalse;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/functioncontains(Set storage set, address value) internalviewreturns (bool) {
return set._indexes[value] !=0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/functionlength(Set storage set) internalviewreturns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/functionat(Set storage set, uint256 index) internalviewreturns (address) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(Set storage set) internalviewreturns (address[] memory) {
return set._values;
}
}
// SPDX-License-Identifier: GPL-3.0pragmasolidity 0.8.9;interfaceIAuctions{
structHouse {
// House namestring name;
// House curatoraddresspayable curator;
// House percentage feeuint16 fee;
// Pre-approve added creatorsbool preApproved;
// IPFS hash for metadata (logo, featured creators, pieces, links)string metadata;
// Total bidsuint256 bids;
// Total sales numberuint256 sales;
// Total sales amountuint256 total;
// Total fees amountuint256 feesTotal;
// Counter of active autionsuint256 activeAuctions;
}
structAuction {
// Address of the ERC721 contractaddress tokenContract;
// ERC721 tokenIduint256 tokenId;
// Address of the token owneraddress tokenOwner;
// Length of time in seconds to run the auction for, after the first bid was madeuint256 duration;
// Minimum price of the first biduint256 reservePrice;
// House ID for curator addressuint256 houseId;
// Curator fee for this auctionuint16 fee;
// Whether or not the auction curator has approved the auction to startbool approved;
// The time of the first biduint256 firstBidTime;
// The current highest bid amountuint256 amount;
// The address of the current highest bidderaddresspayable bidder;
// The timestamp when this auction was createduint256 created;
}
structTokenContract {
string name;
address tokenContract;
uint256 bids;
uint256 sales;
uint256 total;
}
structAccount {
string name;
string bioHash;
string pictureHash;
}
structCreatorStats {
uint256 bids;
uint256 sales;
uint256 total;
}
structCollectorStats {
uint256 bids;
uint256 sales;
uint256 bought;
uint256 totalSold;
uint256 totalSpent;
}
structBid {
uint256 timestamp;
address bidder;
uint256 value;
}
structOffer {
address tokenContract;
uint256 tokenId;
addressfrom;
uint256 amount;
uint256 timestamp;
}
eventHouseCreated(uint256indexed houseId
);
eventCreatorAdded(uint256indexed houseId,
addressindexed creator
);
eventCreatorRemoved(uint256indexed houseId,
addressindexed creator
);
eventFeeUpdated(uint256indexed houseId,
uint16 fee
);
eventMetadataUpdated(uint256indexed houseId,
string metadata
);
eventAccountUpdated(addressindexed owner
);
eventAuctionCreated(uint256indexed auctionId
);
eventAuctionApprovalUpdated(uint256indexed auctionId,
bool approved
);
eventAuctionReservePriceUpdated(uint256indexed auctionId,
uint256 reservePrice
);
eventAuctionBid(uint256indexed auctionId,
addressindexed bidder,
uint256 value,
bool firstBid,
bool extended
);
eventAuctionDurationExtended(uint256indexed auctionId,
uint256 duration
);
eventAuctionEnded(uint256indexed auctionId
);
eventAuctionCanceled(uint256indexed auctionId
);
functiontotalHouses() externalviewreturns (uint256);
functiontotalAuctions() externalviewreturns (uint256);
functiontotalContracts() externalviewreturns (uint256);
functiontotalCreators() externalviewreturns (uint256);
functiontotalCollectors() externalviewreturns (uint256);
functiontotalActiveHouses() externalviewreturns (uint256);
functiontotalActiveAuctions() externalviewreturns (uint256);
functiontotalActiveHouseAuctions(uint256 houseId) externalviewreturns (uint256);
functiongetActiveHouses(uint256from, uint256 n) externalviewreturns (uint256[] memory);
functiongetRankedHouses(uint256from, uint256 n) externalviewreturns (uint256[] memory);
functiongetRankedCreators(addressfrom, uint256 n) externalviewreturns (address[] memory);
functiongetRankedCollectors(addressfrom, uint256 n) externalviewreturns (address[] memory);
functiongetRankedContracts(addressfrom, uint256 n) externalviewreturns (address[] memory);
functiongetCollections(address creator) externalviewreturns (address[] memory);
functiongetAuctions(uint256from, uint256 n) externalviewreturns (uint256[] memory);
functiongetHouseAuctions(uint256 houseId, uint256from, uint256 n) externalviewreturns (uint256[] memory);
functiongetHouseQueue(uint256 houseId) externalviewreturns (uint256[] memory);
functiongetCuratorHouses(address curator) externalviewreturns (uint256[] memory);
functiongetCreatorHouses(address creator) externalviewreturns (uint256[] memory);
functiongetHouseCreators(uint256 houseId) externalviewreturns (address[] memory);
functiongetSellerAuctions(address seller) externalviewreturns (uint256[] memory);
functiongetBidderAuctions(address bidder) externalviewreturns (uint256[] memory);
functiongetAuctionBids(uint256 auctionId) externalviewreturns (uint256[] memory);
functiongetPreviousAuctions(bytes32 tokenHash) externalviewreturns (uint256[] memory);
functiongetTokenOffers(bytes32 tokenHash) externalviewreturns (uint256[] memory);
functionregisterTokenContract(address tokenContract
) external;
functionmakeOffer(address tokenContract,
uint256 tokenId
) externalpayable;
functionacceptOffer(uint256 offerId
) external;
functioncancelOffer(uint256 offerId
) external;
functioncreateHouse(stringmemory name,
address curator,
uint16 fee,
bool preApproved,
stringmemory metadata
) external;
functionaddCreator(uint256 houseId,
address creator
) external;
functionremoveCreator(uint256 houseId,
address creator
) external;
functionupdateMetadata(uint256 houseId,
stringmemory metadata
) external;
functionupdateFee(uint256 houseId,
uint16 fee
) external;
functionupdateName(stringmemory name
) external;
functionupdateBio(stringmemory bioHash
) external;
functionupdatePicture(stringmemory pictureHash
) external;
functioncreateAuction(address tokenContract,
uint256 tokenId,
uint256 duration,
uint256 reservePrice,
uint256 houseId
) external;
functionsetAuctionApproval(uint256 auctionId,
bool approved
) external;
functionsetAuctionReservePrice(uint256 auctionId,
uint256 reservePrice
) external;
functioncreateBid(uint256 auctionId
) externalpayable;
functionendAuction(uint256 auctionId
) external;
functionbuyAuction(uint256 auctionId
) externalpayable;
functioncancelAuction(uint256 auctionId
) external;
functionfeature(uint256 auctionId,
uint256 amount
) external;
functioncancelFeature(uint256 auctionId
) external;
functionupdateHouseRank(uint256 houseId
) external;
functionupdateCreatorRank(address creator
) external;
functionupdateCollectorRank(address collector
) external;
functionupdateContractRank(address tokenContract
) external;
}
Contract Source Code
File 4 of 13: IERC165.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/interfaceIERC165{
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/functionsupportsInterface(bytes4 interfaceId) externalviewreturns (bool);
}
Contract Source Code
File 5 of 13: IERC721.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import"../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/interfaceIERC721isIERC165{
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/eventApproval(addressindexed owner, addressindexed approved, uint256indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/eventApprovalForAll(addressindexed owner, addressindexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/functionbalanceOf(address owner) externalviewreturns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functionownerOf(uint256 tokenId) externalviewreturns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/functionsafeTransferFrom(addressfrom,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/functiontransferFrom(addressfrom,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/functionapprove(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functiongetApproved(uint256 tokenId) externalviewreturns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/functionsetApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/functionisApprovedForAll(address owner, address operator) externalviewreturns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/functionsafeTransferFrom(addressfrom,
address to,
uint256 tokenId,
bytescalldata data
) external;
}
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/**
* @title OrderedSet
* @dev Ordered data structure. It has the properties of a mapping of uint256, but members are ordered
* and can be enumerated. Values can be inserted and removed from anywhere. Add, append, remove and
* contains are O(1). Enumerate is O(N).
*/libraryOrderedAddressSet{
structSet {
uint256 count;
mapping (address=>address) _next;
mapping (address=>address) _prev;
}
/**
* @dev Insert a value between two values
*/functioninsert(Set storage set, address prev_, address value, address next_) internal{
set._next[prev_] = value;
set._next[value] = next_;
set._prev[next_] = value;
set._prev[value] = prev_;
set.count +=1;
}
/**
* @dev Insert a value as the new head
*/functionadd(Set storage set, address value) internal{
insert(set, address(0), value, set._next[address(0)]);
}
/**
* @dev Insert a value as the new tail
*/functionappend(Set storage set, address value) internal{
insert(set, set._prev[address(0)], value, address(0));
}
/**
* @dev Remove a value
*/functionremove(Set storage set, address value) internal{
set._next[set._prev[value]] = set._next[value];
set._prev[set._next[value]] = set._prev[value];
delete set._next[value];
delete set._prev[value];
if (set.count >0) {
set.count -=1;
}
}
/**
* @dev Returns the head
*/functionhead(Set storage set) internalviewreturns (address) {
return set._next[address(0)];
}
/**
* @dev Returns the tail
*/functiontail(Set storage set) internalviewreturns (address) {
return set._prev[address(0)];
}
/**
* @dev Returns the length
*/functionlength(Set storage set) internalviewreturns (uint256) {
return set.count;
}
/**
* @dev Returns the next value
*/functionnext(Set storage set, address _value) internalviewreturns (address) {
return set._next[_value];
}
/**
* @dev Returns the previous value
*/functionprev(Set storage set, address _value) internalviewreturns (address) {
return set._prev[_value];
}
/**
* @dev Returns true if the value is in the set
*/functioncontains(Set storage set, address value) internalviewreturns (bool) {
return set._next[address(0)] == value ||
set._next[value] !=address(0) ||
set._prev[value] !=address(0);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(Set storage set) internalviewreturns (address[] memory) {
address[] memory _values =newaddress[](set.count);
address value = set._next[address(0)];
uint256 i =0;
while (value !=address(0)) {
_values[i] = value;
value = set._next[value];
i +=1;
}
return _values;
}
/**
* @dev Return an array with n values in the set, starting after "from"
*/functionvaluesFromN(Set storage set, addressfrom, uint256 n) internalviewreturns (address[] memory) {
address[] memory _values =newaddress[](n);
address value = set._next[from];
uint256 i =0;
while (i < n) {
_values[i] = value;
value = set._next[value];
i +=1;
}
return _values;
}
}
Contract Source Code
File 10 of 13: OrderedSet.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/**
* @title OrderedSet
* @dev Ordered data structure. It has the properties of a mapping of uint256, but members are ordered
* and can be enumerated. Values can be inserted and removed from anywhere. Add, append, remove and
* contains are O(1). Enumerate is O(N).
*/libraryOrderedSet{
structSet {
uint256 count;
mapping (uint256=>uint256) _next;
mapping (uint256=>uint256) _prev;
}
/**
* @dev Insert a value between two values
*/functioninsert(Set storage set, uint256 prev_, uint256 value, uint256 next_) internal{
set._next[prev_] = value;
set._next[value] = next_;
set._prev[next_] = value;
set._prev[value] = prev_;
set.count +=1;
}
/**
* @dev Insert a value as the new head
*/functionadd(Set storage set, uint256 value) internal{
insert(set, 0, value, set._next[0]);
}
/**
* @dev Insert a value as the new tail
*/functionappend(Set storage set, uint256 value) internal{
insert(set, set._prev[0], value, 0);
}
/**
* @dev Remove a value
*/functionremove(Set storage set, uint256 value) internal{
set._next[set._prev[value]] = set._next[value];
set._prev[set._next[value]] = set._prev[value];
delete set._next[value];
delete set._prev[value];
if (set.count >0) {
set.count -=1;
}
}
/**
* @dev Returns the head
*/functionhead(Set storage set) internalviewreturns (uint256) {
return set._next[0];
}
/**
* @dev Returns the tail
*/functiontail(Set storage set) internalviewreturns (uint256) {
return set._prev[0];
}
/**
* @dev Returns the length
*/functionlength(Set storage set) internalviewreturns (uint256) {
return set.count;
}
/**
* @dev Returns the next value
*/functionnext(Set storage set, uint256 _value) internalviewreturns (uint256) {
return set._next[_value];
}
/**
* @dev Returns the previous value
*/functionprev(Set storage set, uint256 _value) internalviewreturns (uint256) {
return set._prev[_value];
}
/**
* @dev Returns true if the value is in the set
*/functioncontains(Set storage set, uint256 value) internalviewreturns (bool) {
return set._next[0] == value ||
set._next[value] !=0||
set._prev[value] !=0;
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(Set storage set) internalviewreturns (uint256[] memory) {
uint256[] memory _values =newuint256[](set.count);
uint256 value = set._next[0];
uint256 i =0;
while (value !=0) {
_values[i] = value;
value = set._next[value];
i +=1;
}
return _values;
}
/**
* @dev Return an array with n values in the set, starting after "from"
*/functionvaluesFromN(Set storage set, uint256from, uint256 n) internalviewreturns (uint256[] memory) {
uint256[] memory _values =newuint256[](n);
uint256 value = set._next[from];
uint256 i =0;
while (i < n) {
_values[i] = value;
value = set._next[value];
i +=1;
}
return _values;
}
}
Contract Source Code
File 11 of 13: RankedAddressSet.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import"./OrderedSet.sol";
import"./OrderedAddressSet.sol";
/**
* @title RankedSet
* @dev Ranked data structure using two ordered sets, a mapping of scores to
* boundary values, a mapping of last ranked scores, and a highest score.
*/libraryRankedAddressSet{
usingOrderedSetforOrderedSet.Set;
usingOrderedAddressSetforOrderedAddressSet.Set;
structRankGroup {
uint256 count;
address start;
address end;
}
structSet {
uint256 highScore;
mapping(uint256=> RankGroup) rankgroups;
mapping(address=>uint256) scores;
OrderedSet.Set rankedScores;
OrderedAddressSet.Set rankedItems;
}
/**
* @dev Add an item at the end of the set
*/functionadd(Set storage set, address item) internal{
set.rankedItems.append(item);
set.rankgroups[0].end = item;
set.rankgroups[0].count +=1;
if (set.rankgroups[0].start ==address(0)) {
set.rankgroups[0].start = item;
}
}
/**
* @dev Remove an item
*/functionremove(Set storage set, address item) internal{
uint256 score = set.scores[item];
delete set.scores[item];
RankGroup storage rankgroup = set.rankgroups[score];
if (rankgroup.count >0) {
rankgroup.count -=1;
}
if (rankgroup.count ==0) {
rankgroup.start =address(0);
rankgroup.end =address(0);
if (score == set.highScore) {
set.highScore = set.rankedScores.next(score);
}
if (score >0) {
set.rankedScores.remove(score);
}
} else {
if (rankgroup.start == item) {
rankgroup.start = set.rankedItems.next(item);
}
if (rankgroup.end == item) {
rankgroup.end = set.rankedItems.prev(item);
}
}
set.rankedItems.remove(item);
}
/**
* @dev Returns the head
*/functionhead(Set storage set) internalviewreturns (address) {
return set.rankedItems._next[address(0)];
}
/**
* @dev Returns the tail
*/functiontail(Set storage set) internalviewreturns (address) {
return set.rankedItems._prev[address(0)];
}
/**
* @dev Returns the length
*/functionlength(Set storage set) internalviewreturns (uint256) {
return set.rankedItems.count;
}
/**
* @dev Returns the next value
*/functionnext(Set storage set, address _value) internalviewreturns (address) {
return set.rankedItems._next[_value];
}
/**
* @dev Returns the previous value
*/functionprev(Set storage set, address _value) internalviewreturns (address) {
return set.rankedItems._prev[_value];
}
/**
* @dev Returns true if the value is in the set
*/functioncontains(Set storage set, address value) internalviewreturns (bool) {
return set.rankedItems._next[address(0)] == value ||
set.rankedItems._next[value] !=address(0) ||
set.rankedItems._prev[value] !=address(0);
}
/**
* @dev Returns a value's score
*/functionscoreOf(Set storage set, address value) internalviewreturns (uint256) {
return set.scores[value];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(Set storage set) internalviewreturns (address[] memory) {
address[] memory _values =newaddress[](set.rankedItems.count);
address value = set.rankedItems._next[address(0)];
uint256 i =0;
while (value !=address(0)) {
_values[i] = value;
value = set.rankedItems._next[value];
i +=1;
}
return _values;
}
/**
* @dev Return an array with n values in the set, starting after "from"
*/functionvaluesFromN(Set storage set, addressfrom, uint256 n) internalviewreturns (address[] memory) {
address[] memory _values =newaddress[](n);
address value = set.rankedItems._next[from];
uint256 i =0;
while (i < n) {
_values[i] = value;
value = set.rankedItems._next[value];
i +=1;
}
return _values;
}
/**
* @dev Rank new score
*/functionrankScore(Set storage set, address item, uint256 newScore) internal{
RankGroup storage rankgroup = set.rankgroups[newScore];
if (newScore > set.highScore) {
remove(set, item);
rankgroup.start = item;
set.highScore = newScore;
set.rankedItems.add(item);
set.rankedScores.add(newScore);
} else {
uint256 score = set.scores[item];
uint256 prevScore = set.rankedScores.prev(score);
if (set.rankgroups[score].count ==1) {
score = set.rankedScores.next(score);
}
remove(set, item);
while (prevScore >0&& newScore > prevScore) {
prevScore = set.rankedScores.prev(prevScore);
}
set.rankedItems.insert(
set.rankgroups[prevScore].end,
item,
set.rankgroups[set.rankedScores.next(prevScore)].start
);
if (rankgroup.count ==0) {
set.rankedScores.insert(prevScore, newScore, score);
rankgroup.start = item;
}
}
rankgroup.end = item;
rankgroup.count +=1;
set.scores[item] = newScore;
}
}
Contract Source Code
File 12 of 13: RankedSet.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import"./OrderedSet.sol";
/**
* @title RankedSet
* @dev Ranked data structure using two ordered sets, a mapping of scores to
* boundary values and counter, a mapping of last ranked scores, and a highest
* score.
*/libraryRankedSet{
usingOrderedSetforOrderedSet.Set;
structRankGroup {
uint256 count;
uint256 start;
uint256 end;
}
structSet {
uint256 highScore;
mapping(uint256=> RankGroup) rankgroups;
mapping(uint256=>uint256) scores;
OrderedSet.Set rankedScores;
OrderedSet.Set rankedItems;
}
/**
* @dev Add an item at the end of the set
*/functionadd(Set storage set, uint256 item) internal{
set.rankedItems.append(item);
set.rankgroups[0].end = item;
set.rankgroups[0].count +=1;
if (set.rankgroups[0].start ==0) {
set.rankgroups[0].start = item;
}
}
/**
* @dev Remove an item
*/functionremove(Set storage set, uint256 item) internal{
uint256 score = set.scores[item];
delete set.scores[item];
RankGroup storage rankgroup = set.rankgroups[score];
if (rankgroup.count >0) {
rankgroup.count -=1;
}
if (rankgroup.count ==0) {
rankgroup.start =0;
rankgroup.end =0;
if (score == set.highScore) {
set.highScore = set.rankedScores.next(score);
}
if (score >0) {
set.rankedScores.remove(score);
}
} else {
if (rankgroup.start == item) {
rankgroup.start = set.rankedItems.next(item);
}
if (rankgroup.end == item) {
rankgroup.end = set.rankedItems.prev(item);
}
}
set.rankedItems.remove(item);
}
/**
* @dev Returns the head
*/functionhead(Set storage set) internalviewreturns (uint256) {
return set.rankedItems._next[0];
}
/**
* @dev Returns the tail
*/functiontail(Set storage set) internalviewreturns (uint256) {
return set.rankedItems._prev[0];
}
/**
* @dev Returns the length
*/functionlength(Set storage set) internalviewreturns (uint256) {
return set.rankedItems.count;
}
/**
* @dev Returns the next value
*/functionnext(Set storage set, uint256 _value) internalviewreturns (uint256) {
return set.rankedItems._next[_value];
}
/**
* @dev Returns the previous value
*/functionprev(Set storage set, uint256 _value) internalviewreturns (uint256) {
return set.rankedItems._prev[_value];
}
/**
* @dev Returns true if the value is in the set
*/functioncontains(Set storage set, uint256 value) internalviewreturns (bool) {
return set.rankedItems._next[0] == value ||
set.rankedItems._next[value] !=0||
set.rankedItems._prev[value] !=0;
}
/**
* @dev Returns a value's score
*/functionscoreOf(Set storage set, uint256 value) internalviewreturns (uint256) {
return set.scores[value];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(Set storage set) internalviewreturns (uint256[] memory) {
uint256[] memory _values =newuint256[](set.rankedItems.count);
uint256 value = set.rankedItems._next[0];
uint256 i =0;
while (value !=0) {
_values[i] = value;
value = set.rankedItems._next[value];
i +=1;
}
return _values;
}
/**
* @dev Return an array with n values in the set, starting after "from"
*/functionvaluesFromN(Set storage set, uint256from, uint256 n) internalviewreturns (uint256[] memory) {
uint256[] memory _values =newuint256[](n);
uint256 value = set.rankedItems._next[from];
uint256 i =0;
while (i < n) {
_values[i] = value;
value = set.rankedItems._next[value];
i +=1;
}
return _values;
}
/**
* @dev Rank new score
*/functionrankScore(Set storage set, uint256 item, uint256 newScore) internal{
RankGroup storage rankgroup = set.rankgroups[newScore];
if (newScore > set.highScore) {
remove(set, item);
rankgroup.start = item;
set.highScore = newScore;
set.rankedItems.add(item);
set.rankedScores.add(newScore);
} else {
uint256 score = set.scores[item];
uint256 prevScore = set.rankedScores.prev(score);
if (set.rankgroups[score].count ==1) {
score = set.rankedScores.next(score);
}
remove(set, item);
while (prevScore >0&& newScore > prevScore) {
prevScore = set.rankedScores.prev(prevScore);
}
set.rankedItems.insert(
set.rankgroups[prevScore].end,
item,
set.rankgroups[set.rankedScores.next(prevScore)].start
);
if (rankgroup.count ==0) {
set.rankedScores.insert(prevScore, newScore, score);
rankgroup.start = item;
}
}
rankgroup.end = item;
rankgroup.count +=1;
set.scores[item] = newScore;
}
}
Contract Source Code
File 13 of 13: UintSet.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/libraryUintSet{
structSet {
// Storage of set valuesuint256[] _values;
// Position of the value in the `values` array, plus 1 because index 0// means a value is not in the set.mapping(uint256=>uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/functionadd(Set storage set, uint256 value) internalreturns (bool) {
if (!contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
returntrue;
} else {
returnfalse;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/functionremove(Set storage set, uint256 value) internalreturns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slotuint256 valueIndex = set._indexes[value];
if (valueIndex !=0) {
// Equivalent to contains(set, value)// To delete an element from the _values array in O(1), we swap the element to delete with the last one in// the array, and then remove the last element (sometimes called as 'swap and pop').// This modifies the order of the array, as noted in {at}.uint256 toDeleteIndex = valueIndex -1;
uint256 lastIndex = set._values.length-1;
if (lastIndex != toDeleteIndex) {
uint256 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slotdelete set._indexes[value];
returntrue;
} else {
returnfalse;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/functioncontains(Set storage set, uint256 value) internalviewreturns (bool) {
return set._indexes[value] !=0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/functionlength(Set storage set) internalviewreturns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/functionat(Set storage set, uint256 index) internalviewreturns (uint256) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(Set storage set) internalviewreturns (uint256[] memory) {
return set._values;
}
}