Skip to content

Commit

Permalink
feat: add contract governance
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris-Hibbert committed Sep 21, 2023
1 parent 3d25c53 commit 974f4f1
Show file tree
Hide file tree
Showing 18 changed files with 1,082 additions and 51 deletions.
32 changes: 29 additions & 3 deletions agoric/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ KREAD_REPO =
EVAL_PERMIT =
EVAL_CODE =
EVAL_CLEAN =
KR_AG_DIR =
PROP_DIR = $(KR_AG_DIR)/contract/src/proposal

include Makefile.paths.local

Expand Down Expand Up @@ -38,6 +40,26 @@ wallet1:
deploy:
agoric deploy contract/kread-deploy-contract.js api/kread-deploy-api.js

kread-committee:
agoric run contract/src/proposal/kread-committee-script.js | tee kread-committee.out
node contract/scripts/parseProposals.js < kread-committee.out | jq -r '.bundles[]' | sort -u > kread-committee-bundles.out
for b in `cat kread-committee-bundles.out` ; do \
agoric publish --node 127.0.0.1:26657 $$b --chain-id agoriclocal --home $(COSMIC_SWINGSET_PATH)/t1/8000 ; \
done
cd $(COSMIC_SWINGSET_PATH); \
make scenario2-core-eval EVAL_PERMIT=$(KR_AG_DIR)/kread-invite-committee-permit.json \
EVAL_CODE=$(KR_AG_DIR)/kread-invite-committee.js EVAL_CLEAN=$(KR_AG_DIR)/kread-invite-committee.js.t scenario2-vote VOTE_PROPOSAL=3 \

start-kread:
agoric run contract/src/proposal/start-kread-script.js | tee start-kread.out
node contract/scripts/parseProposals.js < start-kread.out | jq -r '.bundles[]' | sort -u > start-kread-bundles.out
for b in `cat start-kread-bundles.out` ; do \
agoric publish --node 127.0.0.1:26657 $$b --chain-id agoriclocal --home $(COSMIC_SWINGSET_PATH)/t1/8000 ; \
done
cd $(COSMIC_SWINGSET_PATH); \
make scenario2-core-eval EVAL_PERMIT=$(KR_AG_DIR)/start-kread-permit.json \
EVAL_CODE=$(KR_AG_DIR)/start-kread.js EVAL_CLEAN=$(KR_AG_DIR)/start-kread.js.t scenario2-vote VOTE_PROPOSAL=4 \

kread-bundle:
cd $(VATS_PATH); \
yarn bundle-source --cache-json bundles/ ${KREAD_REPO} kread; \
Expand All @@ -63,12 +85,16 @@ provision-fee-collector:
fund-account:
cd $(COSMIC_SWINGSET_PATH); \
make fund-acct ACCT_ADDR=$(KEPLR_ADDRESS) FUNDS=1000000000000uist; \
make fund-acct ACCT_ADDR=$(KEPLR_ADDRESS) FUNDS=1000000000000ubld; \
make fund-acct ACCT_ADDR=$(KEPLR_ADDRESS) FUNDS=1000000000000ubld; \

fund-pool:
cd $(COSMIC_SWINGSET_PATH); \
make fund-provision-pool \

fund-large-contract:
cd $(COSMIC_SWINGSET_PATH); \
make fund-acct ACCT_ADDR=$(KEPLR_ADDRESS) FUNDS=10000000000000000uist; \

fund-account-atom:
cd $(COSMIC_SWINGSET_PATH); \
make fund-acct ACCT_ADDR=$(KEPLR_ADDRESS) FUNDS=100000000ibc/toyatom; \
Expand All @@ -86,10 +112,10 @@ proposal-2:
# before running make proposal
bootstrap:
make provision-account; \
make fund-account; \
make fund-account; \
make kread-bundle; \
make proposal; \

fund+provision:
make provision-account; \
make fund-account; \
make fund-account; \
3 changes: 2 additions & 1 deletion agoric/Makefile.paths
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ KEPLR_ADDRESS2 = agoric1tq3v943uaycqp90qvuyaqzwdc3eh52xzrcl4p6
KREAD_REPO = /Users/carlostrigo/kryha/agoric/code/Agoric/agoric/contract/src/index.js
EVAL_PERMIT = /Users/carlostrigo/kryha/agoric/code/Agoric/agoric/contract/src/proposal/powers.json
EVAL_CODE = /Users/carlostrigo/kryha/agoric/code/Agoric/agoric/contract/src/proposal/chain-storage-proposal.js
EVAL_CLEAN = $(EVAL_CODE)-clean.js
EVAL_CLEAN = $(EVAL_CODE)-clean.js
KR_AG_DIR = /Users/carlostrigo/agoric-kread/agoric
10 changes: 10 additions & 0 deletions agoric/Makefile.paths.local
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
SDK_PATH =/Users/chris/agoric-sdk
COSMIC_SWINGSET_PATH =/Users/chris/agoric-sdk/packages/cosmic-swingset
VATS_PATH =/Users/chris/agoric-sdk/packages/vats
KEPLR_ADDRESS2 = agoric1tq3v943uaycqp90qvuyaqzwdc3eh52xzrcl4p6
KEPLR_ADDRESS = agoric16cnnlc60cgkp7mgwtj9htf5jlakel85lhvft96
KREAD_REPO = /Users/chris/agoric-kryha/agoric/code/Agoric/agoric/contract/src/index.js
EVAL_PERMIT = /Users/chris/agoric-kryha/agoric/code/Agoric/agoric/contract/src/proposal/powers.json
EVAL_CODE = /Users/chris/agoric-kryha/agoric/code/Agoric/agoric/contract/src/proposal/chain-storage-proposal.js
EVAL_CLEAN = $(EVAL_CODE)-clean.js
KR_AG_DIR = /Users/chris/agoric-kread/agoric
4 changes: 4 additions & 0 deletions agoric/contract/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,18 @@
"@agoric/babel-parser": "^7.6.4",
"@agoric/deploy-script-support": "beta",
"@agoric/ertp": "beta",
"@agoric/governance": "beta",
"@agoric/inter-protocol": "beta",
"@agoric/nat": "dev",
"@agoric/notifier": "beta",
"@agoric/store": "beta",
"@agoric/time": "beta",
"@agoric/vat-data": "^0.5.2",
"@agoric/zoe": "beta",
"@agoric/vats": "beta",
"@endo/bundle-source": "^2.1.1",
"@endo/eventual-send": "^0.14.8",
"@endo/far": "^0.2.18",
"@endo/init": "^0.5.37",
"@endo/marshal": "^0.6.9",
"@endo/ses-ava": "^0.2.40",
Expand Down
41 changes: 41 additions & 0 deletions agoric/contract/scripts/parseProposals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env node

import fs from 'fs';

const Fail = (template, ...args) => {
throw Error(String.raw(template, ...args.map(val => String(val))));
};

/**
* Parse output of `agoric run proposal-builder.js`
*
* @param {string} txt
*
* adapted from packages/boot/test/bootstrapTests/supports.js
*/
const parseProposalParts = txt => {
const evals = [
...txt.matchAll(/swingset-core-eval (?<permit>\S+) (?<script>\S+)/g),
].map(m => {
if (!m.groups) throw Fail`Invalid proposal output ${m[0]}`;
const { permit, script } = m.groups;
return { permit, script };
});
evals.length || Fail`No swingset-core-eval found in proposal output: ${txt}`;

const bundles = [...txt.matchAll(/swingset install-bundle @([^\n]+)/gm)].map(
([, bundle]) => bundle,
);
bundles.length || Fail`No bundles found in proposal output: ${txt}`;

return { evals, bundles };
};

const main = (stdin, readFileSync) => {
const input = readFileSync(stdin.fd).toString();
const parts = parseProposalParts(input);
// relies on console.log printing to stdout unmodified
console.log(JSON.stringify(parts));
};

main(process.stdin, fs.readFileSync);
59 changes: 36 additions & 23 deletions agoric/contract/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import { M } from '@agoric/store';
import { provideAll } from '@agoric/zoe/src/contractSupport/durability.js';
import { prepareRecorderKitMakers } from '@agoric/zoe/src/contractSupport/recorder.js';
import { makeRatio } from '@agoric/zoe/src/contractSupport/ratio.js';
import { InvitationShape } from '@agoric/zoe/src/typeGuards.js';
import { handleParamGovernance } from '@agoric/governance';

import { prepareKreadKit } from './kreadKit.js';
import { RatioObject } from './type-guards.js';

/**
* This contract handles the mint of KREAd characters,
Expand All @@ -26,6 +28,7 @@ import { RatioObject } from './type-guards.js';
/** @type {ContractMeta} */
export const meta = {
privateArgsShape: M.splitRecord({
initialPoserInvitation: InvitationShape,
seed: M.number(),
clock: M.eref(M.remotable('Clock')),
powers: {
Expand Down Expand Up @@ -54,35 +57,39 @@ export const meta = {
royaltyDepositFacet: M.any(),
platformFeeDepositFacet: M.any(),
paymentBrand: M.eref(M.remotable('Brand')),
assetNames: M.splitRecord({ character: M.string(), item: M.string() })
assetNames: M.splitRecord({ character: M.string(), item: M.string() }),
}),
};
harden(meta);

/**
* @param {ZCF} zcf
* @param {ZCF<GovernanceTerms<{}>>} zcf
* @param {{
* seed: number
* powers: { storageNode: StorageNode, marshaller: Marshaller },
* clock: Clock
* defaultCharacters: object[],
* defaultItems: object[],
* initialPoserInvitation: Invitation
* powers: { storageNode: StorageNode, marshaller: Marshaller }
* }} privateArgs
*
*
* @param {Baggage} baggage
*/
export const start = async (zcf, privateArgs, baggage) => {
/**
* @type {{
* paymentBrand: Brand
* mintFee: bigint,
* royaltyRate: RatioObject,
* platformFeeRate: RatioObject,
* mintRoyaltyRate: RatioObject,
* mintPlatformFeeRate: RatioObject,
* royaltyDepositFacet: DepositFacet,
* platformFeeDepositFacet: DepositFacet,
* assetNames: { character: string, item: string },
* }}
*/
/**
* @type {{
* paymentBrand: Brand
* mintFee: bigint,
* royaltyRate: RatioObject,
* platformFeeRate: RatioObject,
* mintRoyaltyRate: RatioObject,
* mintPlatformFeeRate: RatioObject,
* royaltyDepositFacet: DepositFacet,
* platformFeeDepositFacet: DepositFacet,
* assetNames: { character: string, item: string },
* }}
*/
const terms = zcf.getTerms();

// TODO: move to proposal
Expand All @@ -98,6 +105,12 @@ export const start = async (zcf, privateArgs, baggage) => {
marketItemMetricsKit: 'market-item-metrics',
};

const { makeGovernorFacet } = await handleParamGovernance(
zcf,
privateArgs.initialPoserInvitation,
{},
);

// Setting up the mint capabilities here in the prepare function, as discussed with Turadg
// durability is not a concern with these, and defining them here, passing on what's needed
// ensures that the capabilities are where they need to be
Expand All @@ -110,11 +123,7 @@ export const start = async (zcf, privateArgs, baggage) => {
const characterIssuerRecord = characterMint.getIssuerRecord();
const itemIssuerRecord = itemMint.getIssuerRecord();

const {
powers,
clock,
seed,
} = privateArgs;
const { powers, clock, seed } = privateArgs;

const {
mintFee,
Expand Down Expand Up @@ -186,7 +195,11 @@ export const start = async (zcf, privateArgs, baggage) => {
),
);

return harden(kreadKit);
return harden({
creatorFacet: makeGovernorFacet(kreadKit.creator),
// no governed parameters, so no need to augment.
publicFacet: kreadKit.public,
});
};

harden(start);
111 changes: 111 additions & 0 deletions agoric/contract/src/kreadCommitteeCharter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// @jessie-check

import '@agoric/governance/exported.js';
import { M } from '@agoric/store';
import { TimestampShape } from '@agoric/time';
import { prepareExo, provideDurableMapStore } from '@agoric/vat-data';
import '@agoric/zoe/exported.js';
import '@agoric/zoe/src/contracts/exported.js';
import {
InstallationShape,
InstanceHandleShape,
} from '@agoric/zoe/src/typeGuards.js';
import { E } from '@endo/far';

/**
* @file This contract makes it possible for those who govern the KREAd contract
* to call for votes to pause offers.
*/

export const INVITATION_MAKERS_DESC = 'charter member invitation';

/** @type {ContractMeta} */
export const meta = {
customTermsShape: {
binaryVoteCounterInstallation: InstallationShape,
},
upgradability: 'canUpgrade',
};
harden(meta);

/**
* @param {ZCF<{ binaryVoteCounterInstallation: Installation }>} zcf
* @param {undefined} privateArgs
* @param {import('@agoric/vat-data').Baggage} baggage
*/
export const start = async (zcf, privateArgs, baggage) => {
const { binaryVoteCounterInstallation: counter } = zcf.getTerms();
/** @type {MapStore<Instance, GovernorCreatorFacet<any>>} */
const instanceToGovernor = provideDurableMapStore(
baggage,
'instanceToGovernor',
);

const makeOfferFilterInvitation = (instance, strings, deadline) => {
const voteOnOfferFilterHandler = seat => {
seat.exit();

const governor = instanceToGovernor.get(instance);
return E(governor).voteOnOfferFilter(counter, deadline, strings);
};

return zcf.makeInvitation(voteOnOfferFilterHandler, 'vote on offer filter');
};

const MakerI = M.interface('Charter InvitationMakers', {
VoteOnPauseOffers: M.call(
InstanceHandleShape,
M.arrayOf(M.string()),
TimestampShape,
).returns(M.promise()),
});

// durable so that when this contract is upgraded this ocap held
// by committee members (from their invitations) stay capable
const invitationMakers = prepareExo(
baggage,
'Charter Invitation Makers',
MakerI,
{
VoteOnPauseOffers: makeOfferFilterInvitation,
},
);

const charterMemberHandler = seat => {
seat.exit();
return harden({ invitationMakers });
};

const CharterCreatorI = M.interface('Charter creatorFacet', {
addInstance: M.call(InstanceHandleShape, M.any())
.optional(M.string())
.returns(),
makeCharterMemberInvitation: M.call().returns(M.promise()),
});

const creatorFacet = prepareExo(
baggage,
'Charter creatorFacet',
CharterCreatorI,
{
/**
* @param {Instance} governedInstance
* @param {GovernorCreatorFacet<any>} governorFacet
* @param {string} [label] for diagnostic use only
*/
addInstance: (governedInstance, governorFacet, label) => {
console.log('charter: adding instance', label);
instanceToGovernor.init(governedInstance, governorFacet);
},
makeCharterMemberInvitation: () =>
zcf.makeInvitation(charterMemberHandler, INVITATION_MAKERS_DESC),
},
);

return harden({ creatorFacet });
};
harden(start);

/**
* @typedef {import('@agoric/zoe/src/zoeService/utils.js').StartedInstanceKit<start>} KreadCharterStartResult
*/
4 changes: 2 additions & 2 deletions agoric/contract/src/kreadKit.js
Original file line number Diff line number Diff line change
Expand Up @@ -1772,8 +1772,8 @@ export const prepareKreadKit = async (
},
},
);
const { public: publicFacet, creator: creatorFacet } = makeKreadKitInternal();
return harden({ publicFacet, creatorFacet });
const facets = makeKreadKitInternal();
return harden({ public: facets.public, creator: facets.creator });
};

harden(prepareKreadKit);
Loading

0 comments on commit 974f4f1

Please sign in to comment.