From 2c876c342b0ab795b6bb4bff9a08257a09495232 Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Mon, 8 Aug 2022 11:45:31 -0700 Subject: [PATCH] refactor: make satisfiesWant/satisfiesGive compatible with Multiples They need to return 0 or 1, so they can return a count with Multiples. Added tests for satisfiesWant, since it's exported. --- packages/zoe/src/contractFacet/offerSafety.js | 16 ++++++++++++---- packages/zoe/src/contractSupport/zoeHelpers.js | 6 ++++-- packages/zoe/src/zoeService/types.js | 1 + packages/zoe/test/unitTests/test-offerSafety.js | 15 ++++++++++++++- packages/zoe/test/unitTests/zcf/test-zcf.js | 6 +++--- 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/packages/zoe/src/contractFacet/offerSafety.js b/packages/zoe/src/contractFacet/offerSafety.js index d37e10db6c84..e915e54300d8 100644 --- a/packages/zoe/src/contractFacet/offerSafety.js +++ b/packages/zoe/src/contractFacet/offerSafety.js @@ -7,20 +7,25 @@ import { AmountMath } from '@agoric/ertp'; * allocationAmount greater than or equal to requiredAmount for every * keyword of giveOrWant? * + * To prepare for multiples, satisfiesWant and satisfiesGive return 0 or 1. + * isOfferSafe will still be boolean. When we have Multiples, satisfiesWant and + * satisfiesGive will tell how many times the offer was matched. + * * @param {AmountKeywordRecord} giveOrWant * @param {AmountKeywordRecord} allocation + * @returns {0|1} */ const satisfiesInternal = (giveOrWant = {}, allocation) => { const isGTEByKeyword = ([keyword, requiredAmount]) => { // If there is no allocation for a keyword, we know the giveOrWant // is not satisfied without checking further. if (allocation[keyword] === undefined) { - return false; + return 0; } const allocationAmount = allocation[keyword]; - return AmountMath.isGTE(allocationAmount, requiredAmount); + return AmountMath.isGTE(allocationAmount, requiredAmount) ? 1 : 0; }; - return Object.entries(giveOrWant).every(isGTEByKeyword); + return Object.entries(giveOrWant).every(isGTEByKeyword) ? 1 : 0; }; /** @@ -77,8 +82,11 @@ const satisfiesGive = (proposal, allocation) => */ function isOfferSafe(proposal, allocation) { return ( - satisfiesGive(proposal, allocation) || satisfiesWant(proposal, allocation) + satisfiesGive(proposal, allocation) > 0 || + satisfiesWant(proposal, allocation) > 0 ); } +harden(isOfferSafe); +harden(satisfiesWant); export { isOfferSafe, satisfiesWant }; diff --git a/packages/zoe/src/contractSupport/zoeHelpers.js b/packages/zoe/src/contractSupport/zoeHelpers.js index 5798868e5fdc..29ca0068ba03 100644 --- a/packages/zoe/src/contractSupport/zoeHelpers.js +++ b/packages/zoe/src/contractSupport/zoeHelpers.js @@ -37,12 +37,14 @@ export const assertIssuerKeywords = (zcf, expected) => { * check; whether the allocation constitutes a refund is not * checked. The update is merged with currentAllocation * (update's values prevailing if the keywords are the same) - * to produce the newAllocation. + * to produce the newAllocation. The return value is 0 for + * false and 1 for true. When multiples are introduced, any + * positive return value will mean true. * * @param {ZCF} zcf * @param {ZcfSeatPartial} seat * @param {AmountKeywordRecord} update - * @returns {boolean} + * @returns {0|1} */ export const satisfies = (zcf, seat, update) => { const currentAllocation = seat.getCurrentAllocation(); diff --git a/packages/zoe/src/zoeService/types.js b/packages/zoe/src/zoeService/types.js index 3845e2bd2205..306b96b5817b 100644 --- a/packages/zoe/src/zoeService/types.js +++ b/packages/zoe/src/zoeService/types.js @@ -182,6 +182,7 @@ * @property {() => Promise} getOfferResult * @property {() => void=} tryExit * @property {() => Promise} hasExited + * @property {() => Promise<0|1>} wasWantSatisfied * * @property {() => Promise} getCurrentAllocationJig * Labelled "Jig" because it *should* only be used for tests, though diff --git a/packages/zoe/test/unitTests/test-offerSafety.js b/packages/zoe/test/unitTests/test-offerSafety.js index fb99701a8b54..5cd0527eea08 100644 --- a/packages/zoe/test/unitTests/test-offerSafety.js +++ b/packages/zoe/test/unitTests/test-offerSafety.js @@ -3,7 +3,10 @@ // eslint-disable-next-line import/no-extraneous-dependencies import { test } from '@agoric/zoe/tools/prepare-test-env-ava.js'; -import { isOfferSafe } from '../../src/contractFacet/offerSafety.js'; +import { + isOfferSafe, + satisfiesWant, +} from '../../src/contractFacet/offerSafety.js'; import { setup } from './setupBasicMints.js'; // Potential outcomes: @@ -34,6 +37,7 @@ test('isOfferSafe - more than want, more than give', t => { const amounts = harden({ A: moola(10n), B: simoleans(7n), C: bucks(8n) }); t.truthy(isOfferSafe(proposal, amounts)); + t.is(satisfiesWant(proposal, amounts), 1); }); // more than want, less than give -> true @@ -47,6 +51,7 @@ test('isOfferSafe - more than want, less than give', t => { const amounts = harden({ A: moola(1n), B: simoleans(7n), C: bucks(8n) }); t.truthy(isOfferSafe(proposal, amounts)); + t.is(satisfiesWant(proposal, amounts), 1); }); // more than want, equal to give -> true @@ -60,6 +65,7 @@ test('isOfferSafe - more than want, equal to give', t => { const amounts = harden({ A: moola(9n), B: simoleans(6n), C: bucks(7n) }); t.truthy(isOfferSafe(proposal, amounts)); + t.is(satisfiesWant(proposal, amounts), 1); }); // less than want, more than give -> true @@ -73,6 +79,7 @@ test('isOfferSafe - less than want, more than give', t => { const amounts = harden({ A: moola(7n), B: simoleans(9n), C: bucks(19n) }); t.truthy(isOfferSafe(proposal, amounts)); + t.is(satisfiesWant(proposal, amounts), 0); }); // less than want, less than give -> false @@ -86,6 +93,7 @@ test('isOfferSafe - less than want, less than give', t => { const amounts = harden({ A: moola(7n), B: simoleans(5n), C: bucks(6n) }); t.falsy(isOfferSafe(proposal, amounts)); + t.is(satisfiesWant(proposal, amounts), 0); }); // less than want, equal to give -> true @@ -99,6 +107,7 @@ test('isOfferSafe - less than want, equal to give', t => { const amounts = harden({ A: moola(1n), B: simoleans(5n), C: bucks(7n) }); t.truthy(isOfferSafe(proposal, amounts)); + t.is(satisfiesWant(proposal, amounts), 0); }); // equal to want, more than give -> true @@ -112,6 +121,7 @@ test('isOfferSafe - equal to want, more than give', t => { const amounts = harden({ A: moola(2n), B: simoleans(6n), C: bucks(8n) }); t.truthy(isOfferSafe(proposal, amounts)); + t.is(satisfiesWant(proposal, amounts), 1); }); // equal to want, less than give -> true @@ -125,6 +135,7 @@ test('isOfferSafe - equal to want, less than give', t => { const amounts = harden({ A: moola(0n), B: simoleans(6n), C: bucks(0n) }); t.truthy(isOfferSafe(proposal, amounts)); + t.is(satisfiesWant(proposal, amounts), 1); }); // equal to want, equal to give -> true @@ -138,6 +149,7 @@ test('isOfferSafe - equal to want, equal to give', t => { const amounts = harden({ A: moola(1n), B: simoleans(6n), C: bucks(7n) }); t.truthy(isOfferSafe(proposal, amounts)); + t.is(satisfiesWant(proposal, amounts), 1); }); test('isOfferSafe - empty proposal', t => { @@ -146,4 +158,5 @@ test('isOfferSafe - empty proposal', t => { const amounts = harden({ A: moola(1n), B: simoleans(6n), C: bucks(7n) }); t.truthy(isOfferSafe(proposal, amounts)); + t.is(satisfiesWant(proposal, amounts), 1); }); diff --git a/packages/zoe/test/unitTests/zcf/test-zcf.js b/packages/zoe/test/unitTests/zcf/test-zcf.js index 35c253a6734b..a22ceb5c16e2 100644 --- a/packages/zoe/test/unitTests/zcf/test-zcf.js +++ b/packages/zoe/test/unitTests/zcf/test-zcf.js @@ -1440,7 +1440,7 @@ test('wasWantSatisfied: no', async t => { ); await zcfSeat.exit(); - t.false(await E(userSeat).wasWantSatisfied()); + t.is(await E(userSeat).wasWantSatisfied(), 0); }); test('wasWantSatisfied: yes', async t => { @@ -1460,7 +1460,7 @@ test('wasWantSatisfied: yes', async t => { doubloonMint.mintGains(harden({ Bonus: doubloonAmount }), zcfSeat); await zcfSeat.exit(); - t.true(await E(userSeat).wasWantSatisfied()); + t.is(await E(userSeat).wasWantSatisfied(), 1); }); test('wasWantSatisfied as promise', async t => { @@ -1479,7 +1479,7 @@ test('wasWantSatisfied as promise', async t => { ); const outcome = E.when(E(userSeat).wasWantSatisfied(), result => - t.true(result), + t.is(result, 1), ); doubloonMint.mintGains(harden({ Bonus: doubloonAmount }), zcfSeat);