Add SetMap type for mapping all requests
This commit is contained in:
parent
81dd4c203f
commit
eebf3a0709
|
@ -10,6 +10,8 @@ import "./libs/SetMap.sol";
|
|||
|
||||
contract Marketplace is Collateral, Proofs {
|
||||
using EnumerableSet for EnumerableSet.Bytes32Set;
|
||||
using EnumerableSet for EnumerableSet.AddressSet;
|
||||
using SetMap for SetMap.Bytes32SetMap;
|
||||
using SetMap for SetMap.AddressSetMap;
|
||||
|
||||
type RequestId is bytes32;
|
||||
|
@ -20,8 +22,9 @@ contract Marketplace is Collateral, Proofs {
|
|||
mapping(RequestId => Request) private requests;
|
||||
mapping(RequestId => RequestContext) private requestContexts;
|
||||
mapping(SlotId => Slot) private slots;
|
||||
mapping(address => EnumerableSet.Bytes32Set) private activeRequests;
|
||||
SetMap.AddressSetMap private activeSlots;
|
||||
// mapping(address => EnumerableSet.Bytes32Set) private activeRequests;
|
||||
SetMap.AddressSetMap private activeRequests;
|
||||
SetMap.Bytes32SetMap private activeSlots;
|
||||
|
||||
constructor(
|
||||
IERC20 _token,
|
||||
|
@ -38,11 +41,12 @@ contract Marketplace is Collateral, Proofs {
|
|||
}
|
||||
|
||||
function myRequests() public view returns (RequestId[] memory) {
|
||||
return _toRequestIds(activeRequests[msg.sender].values());
|
||||
SetMap.AddressSetMapKey key = _toAddressSetMapKey(msg.sender);
|
||||
return _toRequestIds(activeRequests.values(key));
|
||||
}
|
||||
|
||||
function allRequests() public view returns(RequestId[] memory) {
|
||||
return _toRequestIds(activeSlots.keys());
|
||||
return _toRequestIds(activeRequests.values());
|
||||
}
|
||||
|
||||
function mySlots(RequestId requestId)
|
||||
|
@ -50,8 +54,8 @@ contract Marketplace is Collateral, Proofs {
|
|||
view
|
||||
returns (SlotId[] memory)
|
||||
{
|
||||
bytes32[] memory slotIds = activeSlots.values(_toSetMapKey(requestId),
|
||||
msg.sender);
|
||||
bytes32[] memory slotIds =
|
||||
activeSlots.values(_toBytes32SetMapKey(requestId), msg.sender);
|
||||
return _toSlotIds(slotIds);
|
||||
}
|
||||
|
||||
|
@ -74,7 +78,8 @@ contract Marketplace is Collateral, Proofs {
|
|||
context.endsAt = block.timestamp + request.ask.duration;
|
||||
_setProofEnd(_toEndId(id), context.endsAt);
|
||||
|
||||
activeRequests[request.client].add(RequestId.unwrap(id));
|
||||
activeRequests.add(_toAddressSetMapKey(request.client),
|
||||
RequestId.unwrap(id));
|
||||
|
||||
_createLock(_toLockId(id), request.expiry);
|
||||
|
||||
|
@ -110,7 +115,7 @@ contract Marketplace is Collateral, Proofs {
|
|||
slot.requestId = requestId;
|
||||
RequestContext storage context = _context(requestId);
|
||||
context.slotsFilled += 1;
|
||||
activeSlots.add(_toSetMapKey(requestId),
|
||||
activeSlots.add(_toBytes32SetMapKey(requestId),
|
||||
slot.host,
|
||||
SlotId.unwrap(slotId));
|
||||
emit SlotFilled(requestId, slotIndex, slotId);
|
||||
|
@ -139,7 +144,7 @@ contract Marketplace is Collateral, Proofs {
|
|||
|
||||
_unexpectProofs(_toProofId(slotId));
|
||||
|
||||
activeSlots.remove(_toSetMapKey(requestId),
|
||||
activeSlots.remove(_toBytes32SetMapKey(requestId),
|
||||
slot.host,
|
||||
SlotId.unwrap(slotId));
|
||||
slot.host = address(0);
|
||||
|
@ -156,8 +161,9 @@ contract Marketplace is Collateral, Proofs {
|
|||
context.state = RequestState.Failed;
|
||||
_setProofEnd(_toEndId(requestId), block.timestamp - 1);
|
||||
context.endsAt = block.timestamp - 1;
|
||||
activeRequests[request.client].remove(RequestId.unwrap(requestId));
|
||||
activeSlots.clear(_toSetMapKey(requestId));
|
||||
activeRequests.remove(_toAddressSetMapKey(request.client),
|
||||
RequestId.unwrap(requestId));
|
||||
activeSlots.clear(_toBytes32SetMapKey(requestId));
|
||||
emit RequestFailed(requestId);
|
||||
|
||||
// TODO: burn all remaining slot collateral (note: slot collateral not
|
||||
|
@ -174,11 +180,12 @@ contract Marketplace is Collateral, Proofs {
|
|||
RequestContext storage context = _context(requestId);
|
||||
Request storage request = _request(requestId);
|
||||
context.state = RequestState.Finished;
|
||||
activeRequests[request.client].remove(RequestId.unwrap(requestId));
|
||||
activeRequests.remove(_toAddressSetMapKey(request.client),
|
||||
RequestId.unwrap(requestId));
|
||||
SlotId slotId = _toSlotId(requestId, slotIndex);
|
||||
Slot storage slot = _slot(slotId);
|
||||
require(!slot.hostPaid, "Already paid");
|
||||
activeSlots.remove(_toSetMapKey(requestId),
|
||||
activeSlots.remove(_toBytes32SetMapKey(requestId),
|
||||
slot.host,
|
||||
SlotId.unwrap(slotId));
|
||||
uint256 amount = pricePerSlot(requests[requestId]);
|
||||
|
@ -201,7 +208,8 @@ contract Marketplace is Collateral, Proofs {
|
|||
// Update request state to Cancelled. Handle in the withdraw transaction
|
||||
// as there needs to be someone to pay for the gas to update the state
|
||||
context.state = RequestState.Cancelled;
|
||||
activeRequests[request.client].remove(RequestId.unwrap(requestId));
|
||||
activeRequests.remove(_toAddressSetMapKey(request.client),
|
||||
RequestId.unwrap(requestId));
|
||||
emit RequestCancelled(requestId);
|
||||
|
||||
// TODO: To be changed once we start paying out hosts for the time they
|
||||
|
@ -379,7 +387,7 @@ contract Marketplace is Collateral, Proofs {
|
|||
}
|
||||
}
|
||||
|
||||
function _toRequestIds(SetMap.Key[] memory array)
|
||||
function _toRequestIds(SetMap.Bytes32SetMapKey[] memory array)
|
||||
private
|
||||
pure
|
||||
returns (RequestId[] memory result)
|
||||
|
@ -421,12 +429,20 @@ contract Marketplace is Collateral, Proofs {
|
|||
return EndId.wrap(RequestId.unwrap(requestId));
|
||||
}
|
||||
|
||||
function _toSetMapKey(RequestId requestId)
|
||||
function _toBytes32SetMapKey(RequestId requestId)
|
||||
internal
|
||||
pure
|
||||
returns (SetMap.Key)
|
||||
returns (SetMap.Bytes32SetMapKey)
|
||||
{
|
||||
return SetMap.Key.wrap(RequestId.unwrap(requestId));
|
||||
return SetMap.Bytes32SetMapKey.wrap(RequestId.unwrap(requestId));
|
||||
}
|
||||
|
||||
function _toAddressSetMapKey(address addr)
|
||||
internal
|
||||
pure
|
||||
returns (SetMap.AddressSetMapKey)
|
||||
{
|
||||
return SetMap.AddressSetMapKey.wrap(addr);
|
||||
}
|
||||
|
||||
function _notEqual(RequestId a, uint256 b) internal pure returns (bool) {
|
||||
|
|
|
@ -5,28 +5,29 @@ import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
|
|||
|
||||
library SetMap {
|
||||
using EnumerableSet for EnumerableSet.Bytes32Set;
|
||||
using EnumerableSet for EnumerableSet.AddressSet;
|
||||
|
||||
type Key is bytes32;
|
||||
type Bytes32SetMapKey is bytes32;
|
||||
|
||||
struct AddressSetMap {
|
||||
mapping(Key =>
|
||||
struct Bytes32SetMap {
|
||||
mapping(Bytes32SetMapKey =>
|
||||
mapping(address =>
|
||||
mapping(uint8 =>
|
||||
EnumerableSet.Bytes32Set))) _values;
|
||||
mapping(Key => uint8) _index;
|
||||
mapping(Bytes32SetMapKey => uint8) _index;
|
||||
EnumerableSet.Bytes32Set _keys;
|
||||
}
|
||||
|
||||
/// @notice Returns the EnumerableSet.Bytes32 containing the values for a key
|
||||
/// and address in an AddressSetMap
|
||||
/// and address in an Bytes32SetMap
|
||||
/// @dev This is used internally to the library only. `.values()` should only
|
||||
/// be called on its return value in a view/pure function.
|
||||
/// @param map AddressSetMap to list values
|
||||
/// @param map Bytes32SetMap to list values
|
||||
/// @param key key of the values to be listed
|
||||
/// @param addr address of the values to be listed
|
||||
/// @return bytes32[] array of bytes32 values
|
||||
function _set(AddressSetMap storage map,
|
||||
Key key,
|
||||
function _set(Bytes32SetMap storage map,
|
||||
Bytes32SetMapKey key,
|
||||
address addr)
|
||||
private
|
||||
view
|
||||
|
@ -36,13 +37,13 @@ library SetMap {
|
|||
return map._values[key][addr][id];
|
||||
}
|
||||
|
||||
/// @notice Lists all values for a key and address in an AddressSetMap
|
||||
/// @param map AddressSetMap to list values
|
||||
/// @notice Lists all values for a key and address in an Bytes32SetMap
|
||||
/// @param map Bytes32SetMap to list values
|
||||
/// @param key key of the values to be listed
|
||||
/// @param addr address of the values to be listed
|
||||
/// @return bytes32[] array of bytes32 values
|
||||
function values(AddressSetMap storage map,
|
||||
Key key,
|
||||
function values(Bytes32SetMap storage map,
|
||||
Bytes32SetMapKey key,
|
||||
address addr)
|
||||
internal
|
||||
view
|
||||
|
@ -54,7 +55,7 @@ library SetMap {
|
|||
function _toKeys(bytes32[] memory array)
|
||||
private
|
||||
pure
|
||||
returns (Key[] memory result)
|
||||
returns (Bytes32SetMapKey[] memory result)
|
||||
{
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly {
|
||||
|
@ -62,44 +63,44 @@ library SetMap {
|
|||
}
|
||||
}
|
||||
|
||||
/// @notice Lists all keys for an AddressSetMap
|
||||
/// @param map AddressSetMap to list keys
|
||||
/// @notice Lists all keys for an Bytes32SetMap
|
||||
/// @param map Bytes32SetMap to list keys
|
||||
/// @return bytes32[] array of bytes32 values
|
||||
function keys(AddressSetMap storage map)
|
||||
function keys(Bytes32SetMap storage map)
|
||||
internal
|
||||
view
|
||||
returns (Key[] memory)
|
||||
returns (Bytes32SetMapKey[] memory)
|
||||
{
|
||||
return _toKeys(map._keys.values());
|
||||
}
|
||||
|
||||
/// @notice Adds a single value to an AddressSetMap
|
||||
/// @param map AddressSetMap to add the value to
|
||||
/// @notice Adds a single value to an Bytes32SetMap
|
||||
/// @param map Bytes32SetMap to add the value to
|
||||
/// @param key key of the value to be added
|
||||
/// @param addr address of the value to be added
|
||||
/// @param value the value to be added
|
||||
/// @return true if the value was added to the set, that is if it was not
|
||||
/// already present.
|
||||
function add(AddressSetMap storage map,
|
||||
Key key,
|
||||
function add(Bytes32SetMap storage map,
|
||||
Bytes32SetMapKey key,
|
||||
address addr,
|
||||
bytes32 value)
|
||||
internal
|
||||
returns (bool)
|
||||
{
|
||||
map._keys.add(Key.unwrap(key));
|
||||
map._keys.add(Bytes32SetMapKey.unwrap(key));
|
||||
return _set(map, key, addr).add(value);
|
||||
}
|
||||
|
||||
/// @notice Removes a single value from an AddressSetMap
|
||||
/// @param map AddressSetMap to remove the value from
|
||||
/// @notice Removes a single value from an Bytes32SetMap
|
||||
/// @param map Bytes32SetMap to remove the value from
|
||||
/// @param key key of the value to be removed
|
||||
/// @param addr address of the value to be removed
|
||||
/// @param value the value to be removed
|
||||
/// @return true if the value was removed from the set, that is if it was
|
||||
/// present.
|
||||
function remove(AddressSetMap storage map,
|
||||
Key key,
|
||||
function remove(Bytes32SetMap storage map,
|
||||
Bytes32SetMapKey key,
|
||||
address addr,
|
||||
bytes32 value)
|
||||
internal
|
||||
|
@ -108,7 +109,7 @@ library SetMap {
|
|||
EnumerableSet.Bytes32Set storage set = _set(map, key, addr);
|
||||
bool success = set.remove(value);
|
||||
if (success && set.length() == 0) {
|
||||
map._keys.remove(Key.unwrap(key));
|
||||
map._keys.remove(Bytes32SetMapKey.unwrap(key));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
@ -116,10 +117,133 @@ library SetMap {
|
|||
/// @notice Clears values for a key.
|
||||
/// @dev Does not clear the addresses for the key, simply updates an index
|
||||
/// such that the next time values for that key and address are
|
||||
/// retrieved, it will return an empty array.
|
||||
/// retrieved, it will reference a new EnumerableSet.
|
||||
/// @param map Bytes32SetMap for which to clear values
|
||||
/// @param key key for which to clear values
|
||||
function clear(Bytes32SetMap storage map, Bytes32SetMapKey key)
|
||||
internal
|
||||
{
|
||||
map._index[key]++;
|
||||
}
|
||||
|
||||
type AddressSetMapKey is address;
|
||||
|
||||
struct AddressSetMap {
|
||||
mapping(AddressSetMapKey =>
|
||||
mapping(uint8 =>
|
||||
EnumerableSet.Bytes32Set)) _values;
|
||||
mapping(AddressSetMapKey => uint8) _index;
|
||||
EnumerableSet.AddressSet _keys;
|
||||
EnumerableSet.Bytes32Set _allValues;
|
||||
}
|
||||
|
||||
/// @notice Returns the EnumerableSet.AddressSet containing the values for a
|
||||
/// key in an AddressSetMap.
|
||||
/// @dev This is used internally to the library only. `.values()` should only
|
||||
/// be called on its return value in a view/pure function.
|
||||
/// @param map AddressSetMap containing the set to be retrieved.
|
||||
/// @param key key of the set to be retrieved.
|
||||
/// @return bytes32[] array of bytes32 values.
|
||||
function _set(AddressSetMap storage map,
|
||||
AddressSetMapKey key)
|
||||
private
|
||||
view
|
||||
returns (EnumerableSet.Bytes32Set storage)
|
||||
{
|
||||
uint8 id = map._index[key];
|
||||
return map._values[key][id];
|
||||
}
|
||||
|
||||
/// @notice Lists all values contained in an AddressSetMap, regardless of
|
||||
/// the key.
|
||||
/// @param map AddressSetMap to list values
|
||||
/// @return bytes32[] array of bytes32 values
|
||||
function values(AddressSetMap storage map)
|
||||
internal
|
||||
view
|
||||
returns (bytes32[] memory)
|
||||
{
|
||||
return map._allValues.values();
|
||||
}
|
||||
|
||||
/// @notice Lists all values for a key in an AddressSetMap
|
||||
/// @param map AddressSetMap to list values
|
||||
/// @param key key of the values to be listed
|
||||
/// @return bytes32[] array of bytes32 values
|
||||
function values(AddressSetMap storage map, AddressSetMapKey key)
|
||||
internal
|
||||
view
|
||||
returns (bytes32[] memory)
|
||||
{
|
||||
return _set(map, key).values();
|
||||
}
|
||||
|
||||
function _toAddressSetMapKeys(address[] memory array)
|
||||
private
|
||||
pure
|
||||
returns (AddressSetMapKey[] memory result)
|
||||
{
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly {
|
||||
result := array
|
||||
}
|
||||
}
|
||||
|
||||
/// @notice Lists all keys for an Bytes32SetMap.
|
||||
/// @param map AddressSetMap to list keys.
|
||||
/// @return bytes32[] array of bytes32 values.
|
||||
function keys(AddressSetMap storage map)
|
||||
internal
|
||||
view
|
||||
returns (AddressSetMapKey[] memory)
|
||||
{
|
||||
return _toAddressSetMapKeys(map._keys.values());
|
||||
}
|
||||
|
||||
/// @notice Adds a single value to an AddressSetMap
|
||||
/// @param map AddressSetMap to add the value to.
|
||||
/// @param key key of the value to be added.
|
||||
/// @param value the value to be added.
|
||||
/// @return true if the value was added to the set, that is if it was not
|
||||
/// already present.
|
||||
function add(AddressSetMap storage map,
|
||||
AddressSetMapKey key,
|
||||
bytes32 value)
|
||||
internal
|
||||
returns (bool)
|
||||
{
|
||||
map._keys.add(AddressSetMapKey.unwrap(key));
|
||||
map._allValues.add(value);
|
||||
return _set(map, key).add(value);
|
||||
}
|
||||
|
||||
/// @notice Removes a single value from an AddressSetMap
|
||||
/// @param map AddressSetMap to remove the value from
|
||||
/// @param key key of the value to be removed
|
||||
/// @param value the value to be removed
|
||||
/// @return true if the value was removed from the set, that is if it was
|
||||
/// present.
|
||||
function remove(AddressSetMap storage map,
|
||||
AddressSetMapKey key,
|
||||
bytes32 value)
|
||||
internal
|
||||
returns (bool)
|
||||
{
|
||||
EnumerableSet.Bytes32Set storage set = _set(map, key);
|
||||
bool success = set.remove(value);
|
||||
if (success && set.length() == 0) {
|
||||
map._keys.remove(AddressSetMapKey.unwrap(key));
|
||||
}
|
||||
map._allValues.remove(value);
|
||||
return success;
|
||||
}
|
||||
|
||||
/// @notice Clears values for a key.
|
||||
/// @dev Updates an index such that the next time values for that key are
|
||||
/// retrieved, it will reference a new EnumerableSet.
|
||||
/// @param map AddressSetMap for which to clear values
|
||||
/// @param key key for which to clear values
|
||||
function clear(AddressSetMap storage map, Key key)
|
||||
function clear(AddressSetMap storage map, AddressSetMapKey key)
|
||||
internal
|
||||
{
|
||||
map._index[key]++;
|
||||
|
|
Loading…
Reference in New Issue