Skip to content

Commit

Permalink
chore: cleanups suggested in review
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris-Hibbert committed Feb 23, 2023
1 parent 48d7f88 commit 4eef984
Show file tree
Hide file tree
Showing 20 changed files with 222 additions and 250 deletions.
1 change: 0 additions & 1 deletion packages/governance/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export const ParamTypes = /** @type {const} */ ({
RATIO: 'ratio',
STRING: 'string',
PASSABLE_RECORD: 'record',
TIMER_SERVICE: 'timerService',
TIMESTAMP: 'timestamp',
RELATIVE_TIME: 'relativeTime',
UNKNOWN: 'unknown',
Expand Down
17 changes: 4 additions & 13 deletions packages/governance/src/contractGovernance/assertions.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { isRemotable } from '@endo/marshal';
import { assertIsRatio } from '@agoric/zoe/src/contractSupport/ratio.js';
import { mustMatch } from '@agoric/store';
import { RelativeTimeRecordShape, TimestampRecordShape } from '@agoric/time';

const { Fail } = assert;

Expand Down Expand Up @@ -42,31 +44,20 @@ const makeAssertBrandedRatio = (name, modelRatio) => {
harden(makeAssertBrandedRatio);

const assertRelativeTime = value => {
isRemotable(value.timerBrand) || Fail`relativeTime must have a brand`;
typeof value.relValue === 'bigint' || Fail`must have a relValue field`;
mustMatch(value, RelativeTimeRecordShape);
};
harden(assertRelativeTime);

const assertTimestamp = value => {
isRemotable(value.timerBrand) || Fail`timestamp must have a brand`;
typeof value.absValue === 'bigint' || Fail`must have an absValue field`;
mustMatch(value, TimestampRecordShape, 'timestamp');
};
harden(assertTimestamp);

const makeAssertTimerService = name => {
return timerService => {
typeof timerService === 'object' ||
Fail`value for ${name} must be a TimerService, was ${timerService}`;
};
};
harden(makeAssertTimerService);

export {
makeLooksLikeBrand,
makeAssertInstallation,
makeAssertInstance,
makeAssertBrandedRatio,
assertRelativeTime,
assertTimestamp,
makeAssertTimerService,
};
11 changes: 0 additions & 11 deletions packages/governance/src/contractGovernance/paramManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
makeAssertInstallation,
makeAssertInstance,
makeLooksLikeBrand,
makeAssertTimerService,
} from './assertions.js';
import { CONTRACT_ELECTORATE } from './governParam.js';

Expand Down Expand Up @@ -47,7 +46,6 @@ const assertElectorateMatches = (paramManager, governedParams) => {
* @property {(name: string, value: Ratio) => ParamManagerBuilder} addRatio
* @property {(name: string, value: import('@endo/marshal').CopyRecord<unknown>) => ParamManagerBuilder} addRecord
* @property {(name: string, value: string) => ParamManagerBuilder} addString
* @property {(name: string, value: import('@agoric/time/src/types').TimerService) => ParamManagerBuilder} addTimerService
* @property {(name: string, value: import('@agoric/time/src/types').Timestamp) => ParamManagerBuilder} addTimestamp
* @property {(name: string, value: import('@agoric/time/src/types').RelativeTime) => ParamManagerBuilder} addRelativeTime
* @property {(name: string, value: any) => ParamManagerBuilder} addUnknown
Expand Down Expand Up @@ -190,13 +188,6 @@ const makeParamManagerBuilder = (publisherKit, zoe) => {
return builder;
};

/** @type {(name: string, value: import('@agoric/time/src/types').TimerService, builder: ParamManagerBuilder) => ParamManagerBuilder} */
const addTimerService = (name, value, builder) => {
const assertTimerService = makeAssertTimerService(name);
buildCopyParam(name, value, assertTimerService, ParamTypes.TIMER_SERVICE);
return builder;
};

/** @type {(name: string, value: import('@agoric/time/src/types').Timestamp, builder: ParamManagerBuilder) => ParamManagerBuilder} */
const addTimestamp = (name, value, builder) => {
buildCopyParam(name, value, assertTimestamp, ParamTypes.TIMESTAMP);
Expand Down Expand Up @@ -381,7 +372,6 @@ const makeParamManagerBuilder = (publisherKit, zoe) => {
getRatio: name => getTypedParam(ParamTypes.RATIO, name),
getRecord: name => getTypedParam(ParamTypes.PASSABLE_RECORD, name),
getString: name => getTypedParam(ParamTypes.STRING, name),
getTimerService: name => getTypedParam(ParamTypes.TIMER_SERVICE, name),
getTimestamp: name => getTypedParam(ParamTypes.TIMESTAMP, name),
getRelativeTime: name => getTypedParam(ParamTypes.RELATIVE_TIME, name),
getUnknown: name => getTypedParam(ParamTypes.UNKNOWN, name),
Expand All @@ -407,7 +397,6 @@ const makeParamManagerBuilder = (publisherKit, zoe) => {
addRatio: (n, v) => addRatio(n, v, builder),
addRecord: (n, v) => addRecord(n, v, builder),
addString: (n, v) => addString(n, v, builder),
addTimerService: (n, v) => addTimerService(n, v, builder),
addRelativeTime: (n, v) => addRelativeTime(n, v, builder),
addTimestamp: (n, v) => addTimestamp(n, v, builder),
build,
Expand Down
12 changes: 3 additions & 9 deletions packages/governance/src/contractHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ import { getMethodNames, objectMap } from '@agoric/internal';
import { ignoreContext } from '@agoric/vat-data';
import { keyEQ, M } from '@agoric/store';
import { AmountShape, BrandShape } from '@agoric/ertp';
import {
RelativeTimeShape,
TimestampShape,
TimerServiceShape,
} from '@agoric/time';
import { RelativeTimeRecordShape, TimestampRecordShape } from '@agoric/time';
import { assertElectorateMatches } from './contractGovernance/paramManager.js';
import { makeParamManagerFromTerms } from './contractGovernance/typedParamManager.js';

Expand All @@ -28,9 +24,8 @@ const publicMixinAPI = harden({
getNat: M.call().returns(M.bigint()),
getRatio: M.call().returns(M.record()),
getString: M.call().returns(M.string()),
getTimerService: M.call().returns(TimerServiceShape),
getTimestamp: M.call().returns(TimestampShape),
getRelativeTime: M.call().returns(RelativeTimeShape),
getTimestamp: M.call().returns(TimestampRecordShape),
getRelativeTime: M.call().returns(RelativeTimeRecordShape),
getUnknown: M.call().returns(M.any()),
});

Expand Down Expand Up @@ -59,7 +54,6 @@ const facetHelpers = (zcf, paramManager) => {
getNat: paramManager.getNat,
getRatio: paramManager.getRatio,
getString: paramManager.getString,
getTimerService: paramManager.getTimerService,
getTimestamp: paramManager.getTimestamp,
getRelativeTime: paramManager.getRelativeTime,
getUnknown: paramManager.getUnknown,
Expand Down
10 changes: 6 additions & 4 deletions packages/governance/src/types-ambient.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@

/**
* @typedef { Amount | Brand | Installation | Instance | bigint |
* Ratio | string | unknown } ParamValue
* Ratio | string | import('@agoric/time/src/types').TimestampRecord |
* import('@agoric/time/src/types').RelativeTimeRecord | unknown } ParamValue
*/

// XXX better to use the manifest constant ParamTypes
Expand All @@ -47,6 +48,8 @@
* T extends 'nat' ? bigint :
* T extends 'ratio' ? Ratio :
* T extends 'string' ? string :
* T extends 'timestamp' ? import('@agoric/time/src/types').TimestampRecord :
* T extends 'relativeTime' ? import('@agoric/time/src/types').RelativeTimeRecord :
* T extends 'unknown' ? unknown :
* never
* } ParamValueForType
Expand Down Expand Up @@ -427,9 +430,8 @@
* @property {(name: string) => bigint} getNat
* @property {(name: string) => Ratio} getRatio
* @property {(name: string) => string} getString
* @property {(name: string) => import('@agoric/time/src/types').TimerService} getTimerService
* @property {(name: string) => import('@agoric/time/src/types').Timestamp} getTimestamp
* @property {(name: string) => import('@agoric/time/src/types').RelativeTime} getRelativeTime
* @property {(name: string) => import('@agoric/time/src/types').TimestampRecord} getTimestamp
* @property {(name: string) => import('@agoric/time/src/types').RelativeTimeRecord} getRelativeTime
* @property {(name: string) => any} getUnknown
* @property {(name: string, proposedValue: ParamValue) => ParamValue} getVisibleValue - for
* most types, the visible value is the same as proposedValue. For Invitations
Expand Down
4 changes: 2 additions & 2 deletions packages/inter-protocol/scripts/add-collateral-core.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ export const psmGovernanceBuilder = async ({
vaults: publishRef(
install(
'../src/vaultFactory/vaultFactory.js',
'../bundles/bundle-vaults.js',
'../bundles/bundle-vaultFactory.js',
),
),
auction: publishRef(
install(
'../src/auction/auctioneer.js',
'../bundles/bundle-auction.js',
'../bundles/bundle-auctioneer.js',
),
),
econCommitteeCharter: publishRef(
Expand Down
2 changes: 1 addition & 1 deletion packages/inter-protocol/scripts/deploy-contracts.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const contractRefs = [
'../bundles/bundle-liquidateMinimum.js',
'../bundles/bundle-reserve.js',
'../bundles/bundle-psm.js',
'../bundles/bundle-auction.js',
'../bundles/bundle-auctioneer.js',
'../../vats/bundles/bundle-mintHolder.js',
];
const contractRoots = contractRefs.map(ref =>
Expand Down
5 changes: 4 additions & 1 deletion packages/inter-protocol/scripts/init-core.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ const installKeyGroups = {
'../src/interchainPool.js',
'../bundles/bundle-interchainPool.js',
],
auction: ['../src/auction/auctioneer.js', '../bundles/bundle-auction.js'],
auction: [
'../src/auction/auctioneer.js',
'../bundles/bundle-auctioneer.js',
],
vaultFactory: [
'../src/vaultFactory/vaultFactory.js',
'../bundles/bundle-vaultFactory.js',
Expand Down
78 changes: 40 additions & 38 deletions packages/inter-protocol/src/auction/auctionBook.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,16 @@ import {
multiplyRatios,
ratioGTE,
} from '@agoric/zoe/src/contractSupport/index.js';
import { TimeMath } from '@agoric/time';
import { E } from '@endo/captp';
import { makeTracer } from '@agoric/internal';

import { makeDiscountBook, makePriceBook } from './discountBook.js';
import {
AuctionState,
isDiscountedPriceHigher,
makeRatioPattern,
makeBrandedRatioPattern,
priceFrom,
} from './util.js';
import { keyToTime } from './sortedOffers.js';

const { Fail } = assert;

Expand All @@ -35,9 +34,11 @@ const { Fail } = assert;
* auction. It holds the book, the lockedPrice, and the collateralSeat that has
* the allocation of assets for sale.
*
* The book contains orders for a particular collateral. It holds two kinds of
* orders: one has a price in terms of a Currency amount, the other is priced as
* a discount (or markup) from the most recent oracle price.
* The book contains orders for the collateral. It holds two kinds of
* orders:
* - Prices express the bid in terms of a Currency amount
* - Discount express the bid in terms of a discount (or markup) from the
* most recent oracle price.
*
* Offers can be added in three ways. When the auction is not active, prices are
* automatically added to the appropriate collection. If a new offer is at or
Expand All @@ -48,12 +49,6 @@ const { Fail } = assert;

const trace = makeTracer('AucBook', false);

const priceFrom = quote =>
makeRatioFromAmounts(
quote.quoteAmount.value[0].amountOut,
quote.quoteAmount.value[0].amountIn,
);

/** @typedef {import('@agoric/vat-data').Baggage} Baggage */

export const makeAuctionBook = async (
Expand All @@ -71,19 +66,19 @@ export const makeAuctionBook = async (
const BidSpecShape = M.or(
{
want: AmountShape,
offerPrice: makeRatioPattern(currencyBrand, collateralBrand),
offerPrice: makeBrandedRatioPattern(currencyBrand, collateralBrand),
},
{
want: AmountShape,
offerDiscount: makeRatioPattern(currencyBrand, currencyBrand),
offerDiscount: makeBrandedRatioPattern(currencyBrand, currencyBrand),
},
);

let assetsForSale = AmountMath.makeEmpty(collateralBrand);
const { zcfSeat: collateralSeat } = zcf.makeEmptySeatKit();
const { zcfSeat: currencySeat } = zcf.makeEmptySeatKit();

let lockedPrice = makeZeroRatio();
let lockedPriceForRound = makeZeroRatio();
let updatingOracleQuote = makeZeroRatio();
E.when(E(collateralBrand).getDisplayInfo(), ({ decimalPlaces = 9n }) => {
// TODO(#6946) use this to keep a current price that can be published in state.
Expand Down Expand Up @@ -191,8 +186,16 @@ export const makeAuctionBook = async (

const isActive = auctionState => auctionState === AuctionState.ACTIVE;

// accept new offer.
const acceptOffer = (seat, price, want, timestamp, auctionState) => {
/**
* Accept an offer expressed as a price. If the auction is active, attempt to
* buy collateral. If any of the offer remains add it to the book.
*
* @param {ZCFSeat} seat
* @param {Ratio} price
* @param {Amount} want
* @param {AuctionState} auctionState
*/
const acceptPriceOffer = (seat, price, want, auctionState) => {
trace('acceptPrice');
// Offer has ZcfSeat, offerArgs (w/price) and timeStamp

Expand All @@ -209,26 +212,29 @@ export const makeAuctionBook = async (
const stillWant = AmountMath.subtract(want, collateralSold);
if (!AmountMath.isEmpty(stillWant)) {
trace('added Offer ', price, stillWant.value);
priceBook.add(seat, price, stillWant, timestamp);
priceBook.add(seat, price, stillWant);
} else {
seat.exit();
}
};

// accept new discount offer.
const acceptDiscountOffer = (
seat,
discount,
want,
timestamp,
auctionState,
) => {
/**
* Accept an offer expressed as a discount (or markup). If the auction is
* active, attempt to buy collateral. If any of the offer remains add it to
* the book.
*
* @param {ZCFSeat} seat
* @param {Ratio} discount
* @param {Amount} want
* @param {AuctionState} auctionState
*/
const acceptDiscountOffer = (seat, discount, want, auctionState) => {
trace('accept discount');
let collateralSold = AmountMath.makeEmptyFromAmount(want);

if (
isActive(auctionState) &&
isDiscountedPriceHigher(discount, curAuctionPrice, lockedPrice)
isDiscountedPriceHigher(discount, curAuctionPrice, lockedPriceForRound)
) {
collateralSold = settle(seat, want);
if (AmountMath.isEmpty(seat.getCurrentAllocation().Currency)) {
Expand All @@ -239,7 +245,7 @@ export const makeAuctionBook = async (

const stillWant = AmountMath.subtract(want, collateralSold);
if (!AmountMath.isEmpty(stillWant)) {
discountBook.add(seat, discount, stillWant, timestamp);
discountBook.add(seat, discount, stillWant);
} else {
seat.exit();
}
Expand All @@ -255,16 +261,14 @@ export const makeAuctionBook = async (
);
},
settleAtNewRate(reduction) {
curAuctionPrice = multiplyRatios(reduction, lockedPrice);
curAuctionPrice = multiplyRatios(reduction, lockedPriceForRound);

const pricedOffers = priceBook.offersAbove(curAuctionPrice);
const discOffers = discountBook.offersAbove(reduction);

// requested price or discount gives no priority beyond specifying which
// round the order will be service in.
const prioritizedOffers = [...pricedOffers, ...discOffers].sort(
([a], [b]) => TimeMath.compareAbs(keyToTime(a), keyToTime(b)),
);
const prioritizedOffers = [...pricedOffers, ...discOffers].sort();

trace(`settling`, pricedOffers.length, discOffers.length);
prioritizedOffers.forEach(([key, { seat, price: p, wanted }]) => {
Expand Down Expand Up @@ -297,30 +301,28 @@ export const makeAuctionBook = async (
},
lockOraclePriceForRound() {
trace(`locking `, updatingOracleQuote);
lockedPrice = updatingOracleQuote;
lockedPriceForRound = updatingOracleQuote;
},

setStartingRate(rate) {
trace('set startPrice', lockedPrice);
curAuctionPrice = multiplyRatios(lockedPrice, rate);
trace('set startPrice', lockedPriceForRound);
curAuctionPrice = multiplyRatios(lockedPriceForRound, rate);
},
addOffer(bidSpec, seat, auctionState) {
mustMatch(bidSpec, BidSpecShape);

if (bidSpec.offerPrice) {
return acceptOffer(
return acceptPriceOffer(
seat,
bidSpec.offerPrice,
bidSpec.want,
0n,
auctionState,
);
} else if (bidSpec.offerDiscount) {
return acceptDiscountOffer(
seat,
bidSpec.offerDiscount,
bidSpec.want,
2n,
auctionState,
);
} else {
Expand Down
Loading

0 comments on commit 4eef984

Please sign in to comment.