-
Notifications
You must be signed in to change notification settings - Fork 231
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Description Ensures the `mintedEarly` store can track multiple settlements for the same amount from the same address. ### Security Considerations Ensures state diagram invariants are upheld. ### Scaling Considerations Same considerations as #10729 - the mapStore could grow large if an attacker spams the settlementAccount with uusdc. In these changes we ensure to delete map store entries when the count goes to 0. ### Documentation Considerations Changes should be clear to maintainers. ### Testing Considerations Adds a new test for the scenario not originally considered. ### Upgrade Considerations The `mintedEarly` kind is a Remotable, so changing from a `SetStore` to a `MapStore` does not seem to affect upgradability. These change should be included in the FUSDC GTM CE.
- Loading branch information
Showing
6 changed files
with
373 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -338,7 +338,6 @@ export const prepareAdvancerKit = ( | |
e, | ||
); | ||
} | ||
tmpReturnSeat.exit(); | ||
}, | ||
/** | ||
* @param {Error} error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import { Fail } from '@endo/errors'; | ||
|
||
/** | ||
* @import {Key} from '@endo/patterns'; | ||
*/ | ||
|
||
// TODO provide something like this in a more common place, perhaps as a BagStore | ||
/** | ||
* Creates a bag (multi-set) API that wraps a MapStore where values are counts. | ||
* | ||
* @template {Key} K | ||
* @param {MapStore<K, number>} mapStore | ||
*/ | ||
export const asMultiset = mapStore => | ||
harden({ | ||
/** | ||
* Add an item to the bag, incrementing its count. | ||
* | ||
* @param {K} item The item to add | ||
* @param {number} [count] How many to add (defaults to 1) | ||
*/ | ||
add: (item, count = 1) => { | ||
if (count <= 0) { | ||
throw Fail`Cannot add a non-positive count ${count} to bag`; | ||
} | ||
|
||
if (mapStore.has(item)) { | ||
const currentCount = mapStore.get(item); | ||
mapStore.set(item, currentCount + count); | ||
} else { | ||
mapStore.init(item, count); | ||
} | ||
}, | ||
|
||
/** | ||
* Remove an item from the bag, decrementing its count. If count reaches | ||
* zero, the item is removed completely. | ||
* | ||
* @param {K} item The item to remove | ||
* @param {number} [count] How many to remove (defaults to 1) | ||
* @returns {boolean} Whether the removal was successful | ||
* @throws {Error} If trying to remove more items than exist | ||
*/ | ||
remove: (item, count = 1) => { | ||
if (count <= 0) { | ||
throw Fail`Cannot remove a non-positive count ${count} from bag`; | ||
} | ||
|
||
if (!mapStore.has(item)) { | ||
return false; | ||
} | ||
|
||
const currentCount = mapStore.get(item); | ||
if (currentCount < count) { | ||
throw Fail`Cannot remove ${count} of ${item} from bag; only ${currentCount} exist`; | ||
} | ||
|
||
if (currentCount === count) { | ||
mapStore.delete(item); | ||
} else { | ||
mapStore.set(item, currentCount - count); | ||
} | ||
return true; | ||
}, | ||
|
||
/** | ||
* Get the count of an item in the bag. | ||
* | ||
* @param {K} item The item to check | ||
* @returns {number} The count (0 if not present) | ||
*/ | ||
count: item => { | ||
return mapStore.has(item) ? mapStore.get(item) : 0; | ||
}, | ||
|
||
/** | ||
* Check if the bag contains at least one of the item. | ||
* | ||
* @param {K} item The item to check | ||
* @returns {boolean} Whether the item is in the bag | ||
*/ | ||
has: item => { | ||
return mapStore.has(item); | ||
}, | ||
|
||
/** | ||
* Get all unique items in the bag. | ||
* | ||
* @returns {Iterable<K>} Iterable of unique items | ||
*/ | ||
keys: () => { | ||
return mapStore.keys(); | ||
}, | ||
|
||
/** | ||
* Get all entries (item, count) in the bag. | ||
* | ||
* @returns {Iterable<[K, number]>} Iterable of [item, count] pairs | ||
*/ | ||
entries: () => { | ||
return mapStore.entries(); | ||
}, | ||
|
||
/** | ||
* Get the total number of unique items in the bag. | ||
* | ||
* @returns {number} Number of unique items | ||
*/ | ||
size: () => { | ||
return mapStore.getSize(); | ||
}, | ||
|
||
/** | ||
* Remove all items from the bag. | ||
*/ | ||
clear: () => { | ||
mapStore.clear(); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.