Skip to content

Commit

Permalink
test: verify that governance can set filters and prevent PSM trades
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris-Hibbert committed Aug 24, 2022
1 parent a1008b8 commit ab3e0a1
Show file tree
Hide file tree
Showing 3 changed files with 251 additions and 3 deletions.
10 changes: 7 additions & 3 deletions packages/inter-protocol/src/psm/psm.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const start = async (zcf, privateArgs, baggage) => {
const emptyStable = AmountMath.makeEmpty(stableBrand);
const emptyAnchor = AmountMath.makeEmpty(anchorBrand);

const { augmentPublicFacet, makeGovernorFacet, params } =
const { augmentVirtualPublicFacet, makeVirtualGovernorFacet, params } =
await handleParamGovernance(
zcf,
privateArgs.initialPoserInvitation,
Expand Down Expand Up @@ -257,9 +257,13 @@ export const start = async (zcf, privateArgs, baggage) => {
makeCollectFeesInvitation,
});

const { limitedCreatorFacet, governorFacet } =
// @ts-expect-error over-determined decl of creatorFacet
makeVirtualGovernorFacet(creatorFacet);
const makePSM = vivifyKindMulti(baggage, 'PSM', () => ({}), {
creatorFacet: makeGovernorFacet(creatorFacet),
publicFacet: augmentPublicFacet(publicFacet),
creatorFacet: governorFacet,
limitedCreatorFacet,
publicFacet: augmentVirtualPublicFacet(publicFacet),
});
return makePSM();
};
184 changes: 184 additions & 0 deletions packages/inter-protocol/test/psm/setupPsm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
// @ts-check

import { makeLoopback } from '@endo/captp';
import { E } from '@endo/eventual-send';

import {
makeAgoricNamesAccess,
makePromiseSpace,
} from '@agoric/vats/src/core/utils.js';
import { makeBoard } from '@agoric/vats/src/lib-board.js';
import { Stable } from '@agoric/vats/src/tokens.js';
import { makeZoeKit } from '@agoric/zoe';
import { makeFakeVatAdmin } from '@agoric/zoe/tools/fakeVatAdmin.js';
import buildManualTimer from '@agoric/zoe/tools/manualTimer.js';
import { makeMockChainStorageRoot } from '@agoric/vats/tools/storage-test-utils.js';
import { makeIssuerKit } from '@agoric/ertp';

import { installGovernance, provideBundle } from '../supports.js';
import { startEconomicCommittee } from '../../src/proposals/econ-behaviors.js';
import { startPSM } from '../../src/proposals/startPSM.js';
import { allValues } from '../../src/collect.js';

const psmRoot = './src/psm/psm.js'; // package relative

export const setUpZoeForTest = () => {
const { makeFar } = makeLoopback('zoeTest');

const { zoeService, feeMintAccess: nonFarFeeMintAccess } = makeZoeKit(
makeFakeVatAdmin(() => {}).admin,
undefined,
{
name: Stable.symbol,
assetKind: Stable.assetKind,
displayInfo: Stable.displayInfo,
},
);
/** @type {ERef<ZoeService>} */
const zoe = makeFar(zoeService);
const feeMintAccess = makeFar(nonFarFeeMintAccess);
return {
zoe,
feeMintAccess,
};
};
harden(setUpZoeForTest);
/**
* @typedef {ReturnType<typeof setUpZoeForTest>} FarZoeKit
*/

/**
* @param {TimerService} timer
* @param {FarZoeKit} [farZoeKit]
*/
export const setupPsmBootstrap = async (
timer = buildManualTimer(console.log),
farZoeKit,
) => {
if (!farZoeKit) {
farZoeKit = await setUpZoeForTest();
}
const { zoe } = farZoeKit;

const space = /** @type {any} */ (makePromiseSpace());
const { produce, consume } =
/** @type { import('../../src/proposals/econ-behaviors.js').EconomyBootstrapPowers } */ (
space
);

produce.chainTimerService.resolve(timer);
produce.zoe.resolve(zoe);

const { agoricNames, agoricNamesAdmin, spaces } = makeAgoricNamesAccess();
produce.agoricNames.resolve(agoricNames);
produce.agoricNamesAdmin.resolve(agoricNamesAdmin);

installGovernance(zoe, spaces.installation.produce);
produce.chainStorage.resolve(makeMockChainStorageRoot());
produce.board.resolve(makeBoard());

return { produce, consume, ...spaces };
};

/**
* @param {*} t
* @param {{ committeeName: string, committeeSize: number}} electorateTerms
* @param {ManualTimer | undefined=} timer
* @param {FarZoeKit} [farZoeKit]
*/
export const setupPsm = async (
t,
electorateTerms = { committeeName: 'The Cabal', committeeSize: 1 },
timer = buildManualTimer(t.log),
farZoeKit,
) => {
if (!farZoeKit) {
farZoeKit = await setUpZoeForTest();
}

const knutIssuer = makeIssuerKit('KNUT');
const { feeMintAccess, zoe } = farZoeKit;
const space = await setupPsmBootstrap(timer, farZoeKit);
space.produce.zoe.resolve(farZoeKit.zoe);
space.produce.feeMintAccess.resolve(feeMintAccess);
const { consume, brand, issuer, installation, instance } = space;
const psmBundle = await provideBundle(t, psmRoot, 'psm');
installation.produce.psm.resolve(E(zoe).install(psmBundle));

brand.produce.AUSD.resolve(knutIssuer.brand);
issuer.produce.AUSD.resolve(knutIssuer.issuer);

const istIssuer = await E(zoe).getFeeIssuer();
const istBrand = await E(istIssuer).getBrand();

brand.produce.IST.resolve(istBrand);
issuer.produce.IST.resolve(istIssuer);

await Promise.all([
startEconomicCommittee(space, {
options: { econCommitteeOptions: electorateTerms },
}),
startPSM(space, {
options: {
anchorOptions: {
denom: 'AUSD',
decimalPlaces: 6,
keyword: 'AUSD',
proposedName: 'AUSD',
},
},
}),
]);

const installs = await allValues({
psm: installation.consume.psm,
governor: installation.consume.contractGovernor,
electorate: installation.consume.committee,
counter: installation.consume.binaryVoteCounter,
});

const governorCreatorFacet = consume.psmGovernorCreatorFacet;
const governorInstance = await instance.consume.psmGovernor;
const governorPublicFacet = await E(zoe).getPublicFacet(governorInstance);
const g = {
governorInstance,
governorPublicFacet,
governorCreatorFacet,
};
const governedInstance = E(governorPublicFacet).getGovernedContract();

/** @type { GovernedPublicFacet<PSM> } */
const psmPublicFacet = await E(governorCreatorFacet).getPublicFacet();
const psm = {
psmCreatorFacet: await consume.psmCreatorFacet,
psmPublicFacet,
instance: governedInstance,
};

const committeeCreator = await consume.economicCommitteeCreatorFacet;
const electorateInstance = await instance.consume.economicCommittee;

const poserInvitationP = E(committeeCreator).getPoserInvitation();
const poserInvitationAmount = await E(
E(zoe).getInvitationIssuer(),
).getAmountOf(poserInvitationP);

/** @type {import('@agoric/vats/tools/storage-test-utils.js').MockChainStorageRoot} */
// @ts-expect-error cast
const mockChainStorage = await space.consume.chainStorage;

return {
zoe,
installs,
electorate: installs.electorate,
committeeCreator,
electorateInstance,
governor: g,
psm,
invitationAmount: poserInvitationAmount,
mockChainStorage,
space,
knutIssuer,
};
};
harden(setupPsm);
60 changes: 60 additions & 0 deletions packages/inter-protocol/test/psm/test-governedPsm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// @ts-check

// eslint-disable-next-line import/no-extraneous-dependencies
import { test } from '@agoric/zoe/tools/prepare-test-env-ava.js';

import { AmountMath } from '@agoric/ertp';
import { unsafeMakeBundleCache } from '@agoric/swingset-vat/tools/bundleTool.js';
import buildManualTimer from '@agoric/zoe/tools/manualTimer.js';
import { eventLoopIteration } from '@agoric/zoe/tools/eventLoopIteration.js';
import { E } from '@endo/eventual-send';
import { setupPsm } from './setupPsm.js';

test.before(async t => {
const bundleCache = await unsafeMakeBundleCache('bundles/');
t.context = { bundleCache };
});

test('psm block offers w/Governance', async t => {
const electorateTerms = { committeeName: 'EnBancPanel', committeeSize: 3 };
const timer = buildManualTimer(t.log, 0n, { eventLoopIteration });

const { knutIssuer, zoe, psm, committeeCreator, governor, installs } =
await setupPsm(t, electorateTerms, timer);

const invitations = await E(committeeCreator).getVoterInvitations();
const { governorCreatorFacet } = governor;

// @ts-expect-error undeclared type?
const { details } = await E(governorCreatorFacet).voteOnOfferFilter(
installs.counter,
2n,
harden(['wantStable']),
);
const { positions, questionHandle } = await details;

const exerciseAndVote = invitation => {
const seat = E(zoe).offer(invitation);
const voteFacet = E(seat).getOfferResult();
return E(voteFacet).castBallotFor(questionHandle, [positions[0]]);
};
await Promise.all(invitations.map(exerciseAndVote));

await timer.tick();
await timer.tick();
await timer.tick();

t.deepEqual(['wantStable'], await E(zoe).getOfferFilter(psm.instance));

const giveCentral = AmountMath.make(knutIssuer.brand, 1_000_000n);

await t.throwsAsync(
() =>
E(zoe).offer(
E(psm.psmPublicFacet).makeWantStableInvitation(),
harden({ give: { In: giveCentral } }),
harden({ In: knutIssuer.mint.mintPayment(giveCentral) }),
),
{ message: 'not accepting offer with description "wantStable"' },
);
});

0 comments on commit ab3e0a1

Please sign in to comment.