Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: vote to change swap fee #21

Merged
merged 9 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contract/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"dependencies": {
"@agoric/ertp": "^0.16.3-u14.0",
"@agoric/governance": "^0.10.4-u14.0",
"@agoric/inter-protocol": "0.16.2-u14.1",
"@agoric/vats": "0.15.2-u14.0",
"@agoric/zoe": "^0.26.3-u14.0",
"@endo/bundle-source": "^2.8.0",
Expand Down
280 changes: 280 additions & 0 deletions contract/src/platform-goals/start-governed-contract.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
// @ts-check
import { E } from '@endo/far';

import { allValues, zip } from '../objectTools.js';
import { sanitizePathSegment } from './start-contract.js';

const { values } = Object;

/**
* @template SF
* @typedef {import('@agoric/zoe/src/zoeService/utils').StartResult<SF>} StartResult<SF>
*/

/**
* @template SF
* @typedef {import('@agoric/zoe/src/zoeService/utils').StartParams<SF>} StartParams<SF>
*/

/**
* @typedef {StartResult<
* typeof import('@agoric/governance/src/committee.js').prepare
* >} CommitteeStart
*/

/**
* cf. packages/inter-protocol/src/econCommitteeCharter.js
*/
export const INVITATION_MAKERS_DESC = 'charter member invitation';

export const COMMITTEES_ROOT = 'committees'; // cf startEconCommittee.js in agoric-sdk

export const CONTRACT_ELECTORATE = 'Electorate';

export const ParamTypes = /** @type {const} */ ({
AMOUNT: 'amount',
BRAND: 'brand',
INSTALLATION: 'installation',
INSTANCE: 'instance',
INVITATION: 'invitation',
Copy link
Member Author

@dckc dckc Mar 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IOU a test to check that these constants are in sync with the imports

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

many / most are tested now

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not import constants.js?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rollup.config.mjs that I'm using for core eval scripts so far doesn't grok inter-package module specifiers.
There's a rollup plugin to do that, but I don't (yet) want to give the impression that this is a general module linking approach; for that, folks should use bundleSource via agoric run.

I did write up docs for this approach:

NAT: 'nat',
RATIO: 'ratio',
STRING: 'string',
PASSABLE_RECORD: 'record',
TIMESTAMP: 'timestamp',
RELATIVE_TIME: 'relativeTime',
UNKNOWN: 'unknown',
});

/**
* Like startGovernedInstance but with parameterized committeeCreatorFacet
*
* @template {GovernableStartFn} SF
* @param {{
* zoe: ERef<ZoeService>;
* governedContractInstallation: ERef<Installation<SF>>;
* issuerKeywordRecord?: IssuerKeywordRecord;
* terms: Record<string, unknown>;
* privateArgs: StartParams<SF>['privateArgs'];
* label: string;
* }} zoeArgs
* @param {{
* governedParams: Record<string, unknown>;
* timer: ERef<import('@agoric/time/src/types').TimerService>;
* contractGovernor: ERef<Installation>;
* governorTerms: Record<string, unknown>;
* committeeCreatorFacet: CommitteeStart['creatorFacet'];
* }} govArgs
* @returns {Promise<GovernanceFacetKit<SF>>}
*/
export const startMyGovernedInstance = async (
{
zoe,
governedContractInstallation,
issuerKeywordRecord,
terms,
privateArgs,
label,
},
{
governedParams,
timer,
contractGovernor,
governorTerms,
committeeCreatorFacet,
},
) => {
console.log('Getting poser invitation...');

const poserInvitationP = E(committeeCreatorFacet).getPoserInvitation();
const [initialPoserInvitation, electorateInvitationAmount] =
await Promise.all([
poserInvitationP,
E(E(zoe).getInvitationIssuer()).getAmountOf(poserInvitationP),
]);

const fullGovernorTerms = await allValues({
timer,
governedContractInstallation,
governed: {
terms: {
...terms,
governedParams: {
[CONTRACT_ELECTORATE]: {
type: ParamTypes.INVITATION,
value: electorateInvitationAmount,
},
...governedParams,
},
},
issuerKeywordRecord,
label,
},
...governorTerms,
});
const governorFacets = await E(zoe).startInstance(
contractGovernor,
{},
fullGovernorTerms,
harden({
governed: await allValues({
...privateArgs,
initialPoserInvitation,
}),
}),
`${label}-governor`,
);
const [instance, publicFacet, creatorFacet, adminFacet] = await Promise.all([
E(governorFacets.creatorFacet).getInstance(),
E(governorFacets.creatorFacet).getPublicFacet(),
E(governorFacets.creatorFacet).getCreatorFacet(),
E(governorFacets.creatorFacet).getAdminFacet(),
]);
/** @type {GovernanceFacetKit<SF>} */
const facets = harden({
instance,
publicFacet,
governor: governorFacets.instance,
creatorFacet,
adminFacet,
governorCreatorFacet: governorFacets.creatorFacet,
governorAdminFacet: governorFacets.adminFacet,
});
return facets;
};

/**
* @param {*} creatorFacet
* @param {ERef<NameHub>} namesByAddress
* @param {Record<string, string>} voterAddresses
*/
export const inviteToMyCharter = async (
creatorFacet,
namesByAddress,
voterAddresses,
) =>
Promise.all(
values(voterAddresses).map(async addr => {
const debugName = `econ charter member ${addr}`;
const depositFacet = E(namesByAddress).lookup(addr, 'depositFacet');
const invitation = await E(creatorFacet).makeCharterMemberInvitation();
return E(depositFacet)
.receive(invitation)
.catch(err => console.error(`failed deposit to ${debugName}`, err));
}),
);
harden(inviteToMyCharter);

/**
* @param {string} contractName
* @param {BootstrapPowers} powers
* @param {*} config
*/
export const startMyCharter = async (contractName, powers, config) => {
const committeeName = `${contractName}Committee`;
const charterName = `${contractName}Charter`;

const {
consume: { namesByAddress, zoe },
produce: { [`${charterName}Kit`]: produceKit },
installation: {
consume: { binaryVoteCounter: counterP, econCommitteeCharter: installP },
},
instance: {
produce: { [charterName]: instanceP },
},
} = powers;
const {
[committeeName]: { voterAddresses },
} = config?.options || {};
assert(voterAddresses, 'no voter addresses???');

const [charterInstall, counterInstall] = await Promise.all([
installP,
counterP,
]);
const terms = await allValues({
binaryVoteCounterInstallation: counterInstall,
});

const startResult = await E(zoe).startInstance(
charterInstall,
undefined,
terms,
undefined,
'econCommitteeCharter',
);
instanceP.resolve(startResult.instance);
produceKit.resolve(startResult);

await inviteToMyCharter(
startResult.creatorFacet,
namesByAddress,
voterAddresses,
);
return startResult;
};
harden(startMyCharter);

/**
* @param {string} contractName
* @param {BootstrapPowers} powers
* @param {*} config
*/
export const startMyCommittee = async (contractName, powers, config) => {
const committeeName = `${contractName}Committee`;
const {
consume: { board, chainStorage, namesByAddress, startUpgradable },
produce: { [`${committeeName}Kit`]: produceKit },
installation: {
consume: { committee },
},
instance: {
produce: { [committeeName]: produceInstance },
},
} = powers;
const {
[committeeName]: { voterAddresses },
} = config?.options || {};
assert(voterAddresses, 'no voter addresses???');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assert always passes as long as voteAddresses is an empty object {}. Should we assert that it contains some values?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, yes, we should... but I wouldn't be surprised if some tests would need work to meet that constraint.


const committeesNode = await E(chainStorage).makeChildNode(COMMITTEES_ROOT);
const storageNode = await E(committeesNode).makeChildNode(
sanitizePathSegment(committeeName),
);
const marshaller = await E(board).getPublishingMarshaller();

const privateArgs = {
storageNode,
marshaller,
};

const started = await E(startUpgradable)({
label: committeeName,
installation: await committee,
terms: { committeeName, committeeSize: values(voterAddresses).length },
privateArgs,
});
produceKit.resolve(started);
produceInstance.resolve(started.instance);
console.log(committeeName, 'started');

/** @param {[string, Promise<Invitation>][]} addrInvitations */
const distributeInvitations = async addrInvitations => {
await Promise.all(
addrInvitations.map(async ([addr, invitationP]) => {
const debugName = `econ committee member ${addr}`;
const depositFacet = E(namesByAddress).lookup(addr, 'depositFacet');
await E.when(invitationP, invitation =>
E(depositFacet).receive(invitation),
).catch(err => console.error(`failed deposit to ${debugName}`, err));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried adding an address through the env variable SWAP_GOV_ADDR in the Makefile which seemed to successfully pipe through to this code, but I'm seeing an error here when deploying the contract:

"nameKey" not found: "agoric1rwwley550k9mmk6uq6mm6z4udrg8kyuyvfszjk"

This is confusing because in the logs I can see that this address has a smart wallet and is opening vaults before it gets to this point. Is there something wrong with namesByAddress in this context?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you're running on a chain that doesn't have the fix for this one yet? I don't recall what release it's in.

}),
);
};

/** @type {Promise<Invitation>[]} */
const invitations = await E(started.creatorFacet).getVoterInvitations();

await distributeInvitations(zip(values(voterAddresses), invitations));
return started;
};
4 changes: 4 additions & 0 deletions contract/src/platform-goals/types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import '@agoric/governance/src/types-ambient';
import '@agoric/vats/src/core/types';
import '@agoric/ertp/exported';
import '@agoric/zoe/exported';
Loading
Loading