From 23a206ab8771f9aefa7653d708b3372c481be0d7 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Thu, 14 Mar 2024 17:25:42 -0500 Subject: [PATCH 1/7] docs(governance): figures 1-5 --- main/guides/governance/assets/gov-param-1.mmd | 17 +++++++++++++++++ main/guides/governance/assets/gov-param-2.mmd | 15 +++++++++++++++ main/guides/governance/assets/gov-param-3.mmd | 15 +++++++++++++++ .../governance/assets/gov-param-4-accept.mmd | 14 ++++++++++++++ .../governance/assets/gov-param-5-putq.mmd | 0 5 files changed, 61 insertions(+) create mode 100644 main/guides/governance/assets/gov-param-1.mmd create mode 100644 main/guides/governance/assets/gov-param-2.mmd create mode 100644 main/guides/governance/assets/gov-param-3.mmd create mode 100644 main/guides/governance/assets/gov-param-4-accept.mmd create mode 100644 main/guides/governance/assets/gov-param-5-putq.mmd diff --git a/main/guides/governance/assets/gov-param-1.mmd b/main/guides/governance/assets/gov-param-1.mmd new file mode 100644 index 000000000..24963fb2a --- /dev/null +++ b/main/guides/governance/assets/gov-param-1.mmd @@ -0,0 +1,17 @@ +sequenceDiagram + autonumber + + actor V1 as Voter1 + + participant Core as swaparoo
deployer + + participant Zoe + participant Ctee as swaparoo
committee + + Core-)Zoe: startInstance(committee, ...) + Zoe--)Ctee: start({committeeSize: 1}) + Ctee--)Zoe: { creatorFacet, ... } + Zoe--)Core: { creatorFacet, ... } + Core--)Ctee: E(creatorFacet).getVoterInvitations() + Ctee--)Core: [invitationV1] + Core--)V1: invitationV1 diff --git a/main/guides/governance/assets/gov-param-2.mmd b/main/guides/governance/assets/gov-param-2.mmd new file mode 100644 index 000000000..07cc23774 --- /dev/null +++ b/main/guides/governance/assets/gov-param-2.mmd @@ -0,0 +1,15 @@ +sequenceDiagram + autonumber + + participant Core as swaparoo
deployer + participant Zoe + + participant SG as swaparoo
governor + participant S as swaparoo + + Core-)SG: startInstance(contractGovernor,
{ governedContractInstallation: swaparoo }) + SG--)S: startInstance(swaparoo) + S--)SG: swaparooFacets + SG--)Core: govFacets + Core--)SG: E(govFacets.creatorFacet).getCreatorFacet() + SG--)Core: swaparoo
limitedCreatorFacet diff --git a/main/guides/governance/assets/gov-param-3.mmd b/main/guides/governance/assets/gov-param-3.mmd new file mode 100644 index 000000000..22550db4a --- /dev/null +++ b/main/guides/governance/assets/gov-param-3.mmd @@ -0,0 +1,15 @@ +sequenceDiagram + autonumber + + actor V1 as Voter1 + + participant Core as swaparoo
deployer + + participant Zoe + participant Charter as swaparoo
charter + + Core-)Charter: startInstance(econCommitteeCharter, ...) + Charter--)Core: { creatorFacet, ... } + Core--)Charter: E(creatorFacet).getVoterInvitations() + Charter--)Core: [invitationQ1] + Core--)V1: invitationQ1 diff --git a/main/guides/governance/assets/gov-param-4-accept.mmd b/main/guides/governance/assets/gov-param-4-accept.mmd new file mode 100644 index 000000000..63de82bf0 --- /dev/null +++ b/main/guides/governance/assets/gov-param-4-accept.mmd @@ -0,0 +1,14 @@ +sequenceDiagram + autonumber + + actor V1 as Voter1 + + participant WF as walletFactory + participant Zoe + participant Charter as swaparoo
charter + + V1-)WF: executeOffer({ id: 'v0-accept-charter',
{ invitationSpec: source: 'purse',
description: 'charter member invitation',
instance: swaparooCharter } }) + WF--)Zoe: offer(invitationQ1) + Zoe--)Charter: charterMemberHandler() + Charter--)WF: { invitationMakers: { VoteOnParamChange, ... } } + WF--)V1: { payouts: {} } diff --git a/main/guides/governance/assets/gov-param-5-putq.mmd b/main/guides/governance/assets/gov-param-5-putq.mmd new file mode 100644 index 000000000..e69de29bb From e0ee0b60536ff146d964884600429faacece071f Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Thu, 14 Mar 2024 17:26:01 -0500 Subject: [PATCH 2/7] docs(governance): generated SVG of figures --- main/guides/governance/assets/gov-param-1.svg | 1 + main/guides/governance/assets/gov-param-2.svg | 1 + main/guides/governance/assets/gov-param-3.svg | 1 + main/guides/governance/assets/gov-param-4-accept.svg | 1 + 4 files changed, 4 insertions(+) create mode 100644 main/guides/governance/assets/gov-param-1.svg create mode 100644 main/guides/governance/assets/gov-param-2.svg create mode 100644 main/guides/governance/assets/gov-param-3.svg create mode 100644 main/guides/governance/assets/gov-param-4-accept.svg diff --git a/main/guides/governance/assets/gov-param-1.svg b/main/guides/governance/assets/gov-param-1.svg new file mode 100644 index 000000000..f595c87ac --- /dev/null +++ b/main/guides/governance/assets/gov-param-1.svg @@ -0,0 +1 @@ +swaparoocommitteeZoeswaparoodeployerswaparoocommitteeZoeswaparoodeployerVoter1startInstance(committee, ...)1start({committeeSize: 1})2{ creatorFacet, ... }3{ creatorFacet, ... }4E(creatorFacet).getVoterInvitations()5[invitationV1]6invitationV17Voter1 \ No newline at end of file diff --git a/main/guides/governance/assets/gov-param-2.svg b/main/guides/governance/assets/gov-param-2.svg new file mode 100644 index 000000000..8d491d071 --- /dev/null +++ b/main/guides/governance/assets/gov-param-2.svg @@ -0,0 +1 @@ +swaparooswaparoogovernorZoeswaparoodeployerswaparooswaparoogovernorZoeswaparoodeployerstartInstance(contractGovernor,{ governedContractInstallation: swaparoo })1startInstance(swaparoo)2swaparooFacets3govFacets4E(govFacets.creatorFacet).getCreatorFacet()5swaparoolimitedCreatorFacet6 \ No newline at end of file diff --git a/main/guides/governance/assets/gov-param-3.svg b/main/guides/governance/assets/gov-param-3.svg new file mode 100644 index 000000000..02fa35cff --- /dev/null +++ b/main/guides/governance/assets/gov-param-3.svg @@ -0,0 +1 @@ +swaparoocharterZoeswaparoodeployerswaparoocharterZoeswaparoodeployerVoter1startInstance(econCommitteeCharter, ...)1{ creatorFacet, ... }2E(creatorFacet).getVoterInvitations()3[invitationQ1]4invitationQ15Voter1 \ No newline at end of file diff --git a/main/guides/governance/assets/gov-param-4-accept.svg b/main/guides/governance/assets/gov-param-4-accept.svg new file mode 100644 index 000000000..088d8ae76 --- /dev/null +++ b/main/guides/governance/assets/gov-param-4-accept.svg @@ -0,0 +1 @@ +swaparoocharterZoewalletFactoryswaparoocharterZoewalletFactoryVoter1executeOffer({ id: 'v0-accept-charter',{ invitationSpec: source: 'purse',description: 'charter member invitation',instance: swaparooCharter } })1offer(invitationQ1)2charterMemberHandler()3{ invitationMakers: { VoteOnParamChange, ... } }4{ payouts: {} }5Voter1 \ No newline at end of file From c33b5309005436b65c4e48c4e5bf1395e0fc1223 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Thu, 14 Mar 2024 19:58:16 -0500 Subject: [PATCH 3/7] docs(governance): EC invoke method screenshot --- .../assets/inter-ec-invoke-method.png | Bin 0 -> 47174 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 main/guides/governance/assets/inter-ec-invoke-method.png diff --git a/main/guides/governance/assets/inter-ec-invoke-method.png b/main/guides/governance/assets/inter-ec-invoke-method.png new file mode 100644 index 0000000000000000000000000000000000000000..86a19427afa9008fc244b267a9e0661956733206 GIT binary patch literal 47174 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 literal 0 HcmV?d00001 From 644f8cb7cd508d87d4cfdf6b0b9e93b1e9f4632c Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Thu, 14 Mar 2024 17:26:22 -0500 Subject: [PATCH 4/7] docs(governance): parameter governance; stubs for API gov, filters --- main/guides/governance/index.md | 271 ++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 main/guides/governance/index.md diff --git a/main/guides/governance/index.md b/main/guides/governance/index.md new file mode 100644 index 000000000..7ea23e49c --- /dev/null +++ b/main/guides/governance/index.md @@ -0,0 +1,271 @@ +# Contract Governance + +To help build systems with a good balance of decentralization and executive control, the Agoric platform includes, in addition to chain-wide governance included in the Cosmos SDK platform, an [@agoric/governance](https://github.com/Agoric/agoric-sdk/blob/master/packages/governance/#readme) package with a flexible architecture supporting 3 main forms of control over a contract: + +- **Parameter Governance**: control of parameter values +- **API governance**: capability to invoke particular methods called out by the contract's authors +- **Offer filters**: capability to disable the use of some offers/invitations to deal with emergencies + +::: tip Governance Package Aims + +The emphasis, throughout the design of the governance package, is on ensuring that clients of a contract have visibility into who can make changes, what changes they can make, and what the current state of the controlled values is. + +An [Attacker's Guide](https://github.com/Agoric/agoric-sdk/blob/master/packages/governance/docs/AttackGuide.md) explains the assurances that the governance package aims to support. + +::: + +## Parameter Governance + +In [Starting a Contract Instance](../zoe/#starting-a-contract-instance), we saw that contracts are parameterized by _terms_. Parameter governance supports +having an authorized party, the _Electorate_, change such parameters while the contract is running. + +In [dapp-agoric-basics](https://github.com/Agoric/dapp-agoric-basics), the +swaparoo contract has a governed `Fee` amount parameter: + +```js +const paramTypes = harden( + /** @type {const} */ ({ + Fee: ParamTypes.AMOUNT, + }), +); +``` + +## Reusing Contracts for Electorate, Election Manager + +This dapp uses the `committee.js` contract from `@agoric/governance` for its +electorate. The core eval deployment script starts the swaparoo committee, +gets invitations, and sends them to the the smart wallets of the voters. +In `test-vote-by-committee.js`, the committee consists of just 1 voter. + + + +## Adding Parameter Governance to a Contract + +Adding parameter governance to a contract consists mainly of using `handleParamGovernance(...)`. +We pass it `zcf` so that it can `getTerms()` for initial parameter values, and we +pass `paramTypes` to specify governed parameters and their types. `initialPoserInvitation` +is necessary to set up replacing the electorate. `storageNode` and `marshaller` are used +to publish values of the parameters to vstorage. + +```js +import { handleParamGovernance } from '@agoric/governance/src/contractHelper.js'; + +export const start = async (zcf, privateArgs, baggage) => { +... + const { publicMixin, makeDurableGovernorFacet, params } = + await handleParamGovernance( + zcf, + privateArgs.initialPoserInvitation, + paramTypes, + privateArgs.storageNode, + privateArgs.marshaller, + ); +... +} +``` + +We get back + +- `params`: read-only parameter access. `params.getFee().value` gives us the current value of the `Fee` parameter at any time, for example. +- `publicMixin`: to make the parameter values available via the contract `publicFacet` +- `makeDurableGovernorFacet`: to combine the contract's existing creator facet methods (known as the `limitedCreatorFacet`) with methods for _changing parameter values_. + +```js +export const start = async (zcf, privateArgs, baggage) => { +... + const publicFacet = Far('Public', { + makeFirstInvitation, + ...publicMixin, + }); + const limitedCreatorFacet = Far('Creator', { + makeCollectFeesInvitation() { + return makeCollectFeesInvitation(zcf, feeSeat, feeBrand, 'Fee'); + }, + }); + const { governorFacet } = makeDurableGovernorFacet( + baggage, + limitedCreatorFacet, + ); + return harden({ publicFacet, creatorFacet: governorFacet }); +} +``` + +## Starting a Governed Contract via its Governor + +Changing parameter values is something only the electorate is authorized to do. +To enforce this, a governed contract is started by a _contract governor_. +The contract governor holds the fully-functional creator facet that includes +the capability to change the parameters. The caller that starts the governor +gets only the `limitedCreatorFacet`. + + + +_For clarity, some Zoe API details are ommitted from this figure._ + +## Putting a question via an Election Manager + +An _ElectionManager_ is responsible for letting an appropriate party call `addQuestion()`. The `econCommitteeCharter.js` contract from `@agoric/inter-protocol` is sufficiently general to handle most forms of parameter +governance, so we reuse it here. Swaparoo core eval deployment likewise +starts this contract, asks it for invitations, and sends them to the voters: + + + +_For clarity, some Zoe API details are ommitted from this figure._ + +The committee participant then instructs their smart wallet to +redeem the charter invitation to get a capability to put a question using `VoteOnParamChange`, +using `v0-accept-charter` to identify this offer: + +```js +test.serial('Voter0 accepts charter, committee invitations', async t => { +... + await victor.acceptCharterInvitation('v0-accept-charter'); +... +}); +``` + + + +To exercises their `VoteOnParamChange` capability, +the committee participant makes a [continuing invitation](/glossary/#continuing-invitation-pattern), +referring back to `v0-accept-charter` as `charterAcceptOfferId`: + +```js +const makeVoter = (t, wallet, wellKnown) => { +... + const putQuestion = async (offerId, params, deadline) => { + const instance = await wellKnown.instance[contractName]; // swaparoo instance handle + const path = { paramPath: { key: 'governedParams' } }; + + /** @type {import('@agoric/inter-protocol/src/econCommitteeCharter.js').ParamChangesOfferArgs} */ + const offerArgs = harden({ deadline, params, instance, path }); + + /** @type {import('@agoric/smart-wallet/src/offers.js').OfferSpec} */ + const offer = { + id: offerId, + invitationSpec: { + source: 'continuing', + previousOffer: NonNullish(charterAcceptOfferId), + invitationMakerName: 'VoteOnParamChange', + }, + offerArgs, + proposal: {}, + }; + return doOffer(offer); + }; +}; +``` + +The `offerArgs` include a deadline and details of the params to change: + +```js +test.serial('vote to change swap fee', async t => { +... + const targetFee = IST(50n, 100n); // 50 / 100 = 0.5 IST + const changes = { Fee: targetFee }; +... + const deadline = BigInt(new Date(2024, 6, 1, 9, 10).valueOf() / 1000); + const result = await victor.putQuestion('proposeToSetFee', changes, deadline); + t.log('question is posed', result); +... +}); +``` + +## Voting on a question + +The voter likewise executes an offer to accept their invitation to participate in the committee, +using `v0-join-committee` to identify this offer: + +```js +test.serial('Voter0 accepts charter, committee invitations', async t => { +... + await victor.acceptCommitteeInvitation('v0-join-committee', 0); +... +}); +``` + +To exercise their capability to vote, they make a continuing invitation +referring back to `v0-join-committee` as `committeeOfferId`: + +```js +const makeVoter = (t, wallet, wellKnown) => { +... + const vote = async (offerId, details, position) => { + const chosenPositions = [details.positions[position]]; + + /** @type {import('./wallet-tools.js').OfferSpec} */ + const offer = { + id: offerId, + invitationSpec: { + source: 'continuing', + previousOffer: NonNullish(committeeOfferId), + invitationMakerName: 'makeVoteInvitation', + invitationArgs: harden([chosenPositions, details.questionHandle]), + }, + proposal: {}, + }; + return doOffer(offer); + }; +... +}; +``` + +Each question has a unique `questionHandle` object, part of the `details` +published to vstorage. + +```js +test.serial('vote to change swap fee', async t => { +... + const details = await vstorage.get(`published.committee.swaparoo.latestQuestion`); + t.is(details.electionType, 'param_change'); + const voteResult = await victor.vote('voteToSetFee', details, 0); + t.log('victor voted:', voteResult); +... +}); +``` + +Once the deadline is reached, the contract governor is notified that the question +carried. It instructs the swaparoo contract to change the fee. + +```js +test.serial('vote to change swap fee', async t => { +... + const swapPub = E(zoe).getPublicFacet( + swapPowers.instance.consume[contractName], + ); +... + const after = await E(swapPub).getAmount('Fee'); + t.deepEqual(after, targetFee); +}); +``` + +The swaparoo contract also publishes its updated parameters to vstorage. + +## API Governance + +Just as parameter governance lets an electorate change parameters of a +governed contract, API governance lets the electorate exercise contract APIs; +in particular: creator facet methods on a governed contract. + +For example, in Inter Protocol, the Economic Committee can add and remove +oracle operators: + + + +For details, see: + +- [dapp-econ-gov](https://github.com/Agoric/dapp-econ-gov) +- `vaultFactory` contract in `@agoric/inter-protocol` + +## Offer Filters + +An electorate can instruct a contract to have Zoe filter the offers that +will be passed to the ocntract. See + +- [zcf.setOfferFilter(strings)](/reference/zoe-api/zoe-contract-facet#zcf-setofferfilter-strings). +- [How to add a contract level pause feature? · agoric-sdk · Discussion #8172](https://github.com/Agoric/agoric-sdk/discussions/8172) From 368534dd304baebd45a98a20782ef7585b8beb2e Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Fri, 15 Mar 2024 17:06:21 -0500 Subject: [PATCH 5/7] docs(governance): move from New Features --- main/.vitepress/config.mjs | 3 ++- main/.vitepress/themeConfig/nav.js | 6 ------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/main/.vitepress/config.mjs b/main/.vitepress/config.mjs index ad304cf56..9230f9981 100644 --- a/main/.vitepress/config.mjs +++ b/main/.vitepress/config.mjs @@ -1,4 +1,4 @@ -import { defineConfig } from 'vitepress' +import { defineConfig } from 'vitepress'; import { nav } from './themeConfig/nav.js'; import { rewrites } from './themeConfig/rewrites.js'; @@ -142,6 +142,7 @@ export default defineConfig({ }, { text: 'Zoe Overview', link: '/guides/zoe/' }, { text: 'Contract Upgrade', link: '/guides/zoe/contract-upgrade' }, + { text: 'Contract Governance', link: '/guides/governance/' }, ], }, { diff --git a/main/.vitepress/themeConfig/nav.js b/main/.vitepress/themeConfig/nav.js index 8e4d95fbd..c92cb9ec7 100644 --- a/main/.vitepress/themeConfig/nav.js +++ b/main/.vitepress/themeConfig/nav.js @@ -112,12 +112,6 @@ export const nav = [ text: 'New Features', ariaLabel: 'New Features Menu', items: [ - { - text: 'Governance', - ariaLabel: 'Governance Internal Documentation', - link: - 'https://github.com/Agoric/agoric-sdk/blob/master/packages/governance/docs/', - }, { text: 'Patterns', ariaLabel: 'Patterns Source Code Link', From 6e7689dc8040d4b26885e386e276b954312a11c6 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Fri, 15 Mar 2024 14:25:21 -0500 Subject: [PATCH 6/7] style(glossary): markdown lint --- main/glossary/index.md | 52 +++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/main/glossary/index.md b/main/glossary/index.md index 713c5f077..8df5f58be 100644 --- a/main/glossary/index.md +++ b/main/glossary/index.md @@ -1,6 +1,7 @@ --- sidebar: auto --- + # Glossary This page lists words, expressions, or concepts used by the Agoric technology stack. @@ -42,7 +43,7 @@ abstract right to participate in a particular exchange. An amount is comprised of a [brand](#brand) with a [value](#amountvalue). For example, "4 Quatloos" is an amount with a value of "4" and a brand of the imaginary currency "Quatloos". -**Important**: Amounts are *descriptions* of digital assets, not the actual assets. They have no +**Important**: Amounts are _descriptions_ of digital assets, not the actual assets. They have no economic scarcity or intrinsic value. For example, to make you an offer to buy a magic sword in a game, a party sends you an amount describing the asset of 5 Quatloos they're willing to trade for your @@ -61,6 +62,7 @@ updates its balance to 10 Quatloos. But a deposit of a non-fungible theater tick five tickets is performed by set union rather than by arithmetic. `AmountMath` has a single set of polymorphic methods that deal with different asset kinds: + - `AssetKind.NAT`: Used with [fungible](#fungible) assets. Each amount value is a natural number (non-negative integer). This is the default `AssetKind`. @@ -82,11 +84,12 @@ For more information, see the [ERTP documentation's AmountMath section](/guides/ and the [ERTP API's AmountMath section](/reference/ertp-api/amount-math). + ## AmountValue An AmountValue is the part of an [Amount](#amount) that describes the value of something that can be owned or shared: how much, how many, or a description of a unique asset, such as -$3, Pixel(3,2), or “Seat J12 for the show September 27th at 9:00pm”. +\$3, Pixel(3,2), or “Seat J12 for the show September 27th at 9:00pm”. For a [fungible](#fungible) Amount, the AmountValue is usually a non-negative **BigInt** such as `10n` or `137n`. For a [non-fungible](#non-fungible) Amount, the AmountValue might be a [CopySet](/guides/js-programming/far#pass-styles-and-harden) containing strings naming particular rights or objects representing the rights directly. @@ -128,19 +131,23 @@ and the [ERTP API's Brand section](/reference/ertp-api/brand). ## Bundle Before a contract can be installed on Zoe, its source code must be bundled. This is done by: + ```js import bundleSource from '@endo/bundle-source'; const atomicSwapBundle = await bundleSource( require.resolve('@agoric/zoe/src/contracts/atomicSwap'), ); ``` + The installation operation returns an `installation`, which is an object with a single `getBundle()` method for accessing an installed contract's source code. In most cases, the bundle contains a base64-encoded zip file that you can extract for review. + ```js const { endoZipBase64 } = await E(installation).getBundle(); ``` + ```sh echo "$endoZipBase64" | base64 -d > bundle.zip unzip bundle.zip @@ -158,9 +165,9 @@ Comparable is a deprecated synonym of [Key](#key). ## Contract Installation and Contract Instance -In Agoric documentation, *contract* usually refers to a contract's source code that -defines how the contract works. A contract's source code is *installed* on Zoe. A -contract is *instantiated* to create *contract instances*, which are the active +In Agoric documentation, _contract_ usually refers to a contract's source code that +defines how the contract works. A contract's source code is _installed_ on Zoe. A +contract is _instantiated_ to create _contract instances_, which are the active execution of a contract's code running on Zoe. For example, a realtor has a standard house selling agreement. The contract is the @@ -201,7 +208,7 @@ For more details, see the [agoric-sdk `network` package](https://github.com/Agor ## E() -(Also referred to as *eventual send*) `E()` is a local "bridge" function that +(Also referred to as _eventual send_) `E()` is a local "bridge" function that asynchronously invokes methods on local or remote objects, for example those in another vat, machine, or blockchain. It takes as its argument either a local object or a [presence](#presence) for a remote object or a promise for a local or remote object, and @@ -230,7 +237,7 @@ Guide](https://github.com/endojs/endo/blob/HEAD/packages/ses/docs/guide.md) ## ERTP -*Electronic Rights Transfer Protocol* is a uniform way of transferring tokens and other digital assets, +_Electronic Rights Transfer Protocol_ is a uniform way of transferring tokens and other digital assets, both [fungible](#fungible) and [non-fungible](#non-fungible), in JavaScript. All kinds of digital assets can easily be created and they can be all be transferred in exactly the same ways, with exactly the same security properties. @@ -247,7 +254,7 @@ see the [ERTP documentation](/guides/ertp/) and [ERTP API documentation](/refere To give assets for a possible transaction to an impartial third party, who keeps them until specified conditions are satisfied. For example, Alice wants to sell Bob a ticket for $100. Alice escrows the ticket, and Bob escrows the $100, with Zoe. Zoe -does not give Alice the $100 or Bob the ticket until it has both items. Since neither Alice nor Bob ever holds both items at +does not give Alice the \$100 or Bob the ticket until it has both items. Since neither Alice nor Bob ever holds both items at once, they don't have to trust each other to do the transaction. Zoe automatically escrows payments for transaction offers. ## Eventual Send @@ -261,18 +268,21 @@ For details, see [`E(zoe).offer(...)`](/reference/zoe-api/zoe#proposals). ## Facet -A *facet* is an object that exposes an API or particular view of some larger entity, which may be an object itself. +A _facet_ is an object that exposes an API or particular view of some larger entity, which may be an object itself. You can make any number of facets of an entity. In JavaScript, you often make a facet that forwards method calls: + ```js import { Far } from '@endo/far'; const facet = Far('FacetName', { myMethod: (...args) => oldObject.method(...args), }); ``` + Two Agoric uses are: -- *Deposit Facet*: A facet of a [purse](#purse). Anyone with a reference to its deposit facet object can add + +- _Deposit Facet_: A facet of a [purse](#purse). Anyone with a reference to its deposit facet object can add appropriately branded assets to the purse, but cannot withdraw assets from the purse or find out its balance. -- *Public Facet*: A set of methods and properties for an object that a developer chooses to be publicly visible and usable. +- _Public Facet_: A set of methods and properties for an object that a developer chooses to be publicly visible and usable. ## Fungible @@ -315,6 +325,7 @@ to immediately participate. Otherwise, the contract instance must create any add Every [offer](#offer) to participate in a contract instance must include an invitation to that instance in the first argument to [`E(zoe).offer(...)`](/reference/zoe-api/zoe#e-zoe-offer-invitation-proposal-paymentpkeywordrecord-offerargs), and any wallet receiving one will validate it via the [InvitationIssuer](#invitationissuer). An invitation's [amount](#amount) includes the following properties: + - The contract's installation in Zoe, including access to its source code. - The contract instance this invitation is for. - A handle used to refer to this invitation. @@ -351,7 +362,7 @@ and the [ERTP API's Issuer section](/reference/ertp-api/issuer). ## Key -A *Key* is a [passable](#passable) containing no promises or errors, and can +A _Key_ is a [passable](#passable) containing no promises or errors, and can thus be synchronously compared for structural equivalence with another piece of data. If either side of the comparison contains promises and/or errors, equality is indeterminable. If both are fulfilled down to [presences](#presence) and local state, then either they're the @@ -361,14 +372,14 @@ Keys can be used as elements of CopySets and CopyBags and as keys of CopyMaps (s ## Keyword -A *Keyword* is a string that is an ASCII-only [identifier](https://developer.mozilla.org/en-US/docs/Glossary/Identifier), +A _Keyword_ is a string that is an ASCII-only [identifier](https://developer.mozilla.org/en-US/docs/Glossary/Identifier), starts with an upper case letter, and is not equal to "NaN" or "Infinity". See **[Zoe Data Types](/reference/zoe-api/zoe-data-types#keyword)**. ## Mint -[ERTP](#ertp) has a *mint* object, which creates digital assets. [ZCF](#zcf) provides a different interface to an ERTP mint, called a -*ZCFMint*. Assets and AssetHolders created using ZCFMints can be used in all the same ways as assets created by other ERTP Mints. +[ERTP](#ertp) has a _mint_ object, which creates digital assets. [ZCF](#zcf) provides a different interface to an ERTP mint, called a +_ZCFMint_. Assets and AssetHolders created using ZCFMints can be used in all the same ways as assets created by other ERTP Mints. They interact with Purses, Payments, Brands, and Issuers in the same ways. - ERTP mints create digital assets and are the only ERTP objects with the authority to do so. @@ -413,13 +424,14 @@ Objects have state, behavior, and references. Let's say Object A has references and C, while B and C do not have references to each other. Thus, A can communicate with B and C, and B and C cannot communicate with each other. There is an effective zero-cost firewall between B and C. -An *object capability system* constrains how references are obtained. You can't get one just by +An _object capability system_ constrains how references are obtained. You can't get one just by knowing the name of a global variable or a public class. You can only get a reference via: + - Creation: Functions that create objects get a reference to them. - Construction: Constructors can endow their constructed objects with references, including inherited references. - Introduction: - A has references to B and C. - - B and C do *not* have references to each other + - B and C do _not_ have references to each other - A sends B a reference to C. - B now has a reference to C and can communicate with C. @@ -447,7 +459,7 @@ can immediately cause the [seat](#seat) to exit, getting back the amount it offe ## Passable -A *passable* is something that can be sent to and from remote objects. +A _passable_ is something that can be sent to and from remote objects. Passables include pass-by-copy primitive values such as numbers and strings and pass-by-reference values such as Remotables and Promises. Passables also include [CopyArrays](#copyarray) and [CopyRecords](#copyrecord), which are @@ -494,6 +506,7 @@ expressing [offer](#offer) conditions regarding what assets will be given, what is desired in exchange (protected by [offer safety](#offer-safety)), and an [exit rule](#exit-rule) defining how/when the offer can be canceled. For example: + ```js const myProposal = harden({ give: { Asset: AmountMath.make(quatloosBrand, 4n) }, @@ -501,6 +514,7 @@ const myProposal = harden({ exit: { onDemand: null }, }); ``` + `give` and `want` each associate [Keywords](#keyword) defined by the contract with corresponding [Amounts](#amount) describing respectively what will be given and what is being requested in exchange. See [Offers](/guides/zoe/proposal). @@ -581,7 +595,7 @@ See the [Wallet Guide and API](/guides/wallet/). ## ZCF -*ZCF (Zoe Contract Facet)* is the [facet](#facet) of Zoe exposed to contract code. The Zoe +_ZCF (Zoe Contract Facet)_ is the [facet](#facet) of Zoe exposed to contract code. The Zoe Contract Facet methods can be called synchronously by contract code. See the [ZCF API](/reference/zoe-api/zoe-contract-facet). From 5292aa8f4bc47772846b1329de3f26d7bdb41ac0 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Fri, 15 Mar 2024 14:25:08 -0500 Subject: [PATCH 7/7] docs(smart wallet): elaborate InvitationSpec including continuing - add glossary entry for Continuing Invitation Pattern --- main/glossary/index.md | 6 ++++ main/guides/getting-started/contract-rpc.md | 37 +++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/main/glossary/index.md b/main/glossary/index.md index 8df5f58be..3094cadbe 100644 --- a/main/glossary/index.md +++ b/main/glossary/index.md @@ -163,6 +163,12 @@ unavailable for later use. See Comparable is a deprecated synonym of [Key](#key). +## Continuing Invitation Pattern + +A continuing invitation presumes a previous offer +whose result includes capabilities to make further +invitations. See [`source: 'continuing'`](/guides/getting-started/contract-rpc#source-continuing) in [Specifying Offers](/guides/getting-started/contract-rpc#specifying-offers) for details. + ## Contract Installation and Contract Instance In Agoric documentation, _contract_ usually refers to a contract's source code that diff --git a/main/guides/getting-started/contract-rpc.md b/main/guides/getting-started/contract-rpc.md index c70018e08..ea03a1728 100644 --- a/main/guides/getting-started/contract-rpc.md +++ b/main/guides/getting-started/contract-rpc.md @@ -130,8 +130,41 @@ public facet. -::: tip InvitationSpec Patterns -For more `InvitationSpec` examples, see [How to make an offer from a dapp via the smart wallet? \(InvitationSpec Patterns\) · #8082](https://github.com/Agoric/agoric-sdk/discussions/8082) July 2023 +::: tip InvitationSpec Usage + +Supposing `spec` is an `InvitationSpec`, its `.source` is one of: + +- `purse` - to make an offer with an invitation that is already in the Invitation purse of the smart wallet and agrees with `spec` on `.instance` and `.description` properties. For example, in [dapp-econ-gov](https://github.com/Agoric/dapp-econ-gov), committee members use invitations sent to them when the committee was created. + +- `contract` - the smart wallet makes an invitation by calling a method on the public facet of a specified instance: `E(E(zoe).getPublicFacet(spec.instance)[spec.publicInvitationMaker](...spec.invitationArgs)` + +- `agoricContract` - for example, from [dapp-inter](https://github.com/Agoric/dapp-inter): + +```js +{ + source: 'agoricContract', + instancePath: ['VaultFactory'], + callPipe: [ + ['getCollateralManager', [toLock.brand]], + ['makeVaultInvitation'], + ], + } +``` + +The smart wallet finds the instance using `E(agoricNames).lookup('instance', ...spec.instancePath)` and makes a chain of calls specified by `spec.callPipe`. Each entry in the callPipe is a `[methodName, args?]` pair used to execute a call on the preceding result. The end of the pipe is expected to return an Invitation. + +- `continuing` - For example, `dapp-inter` uses the following `InvitationSpec` to adjust a vault: + +```js +{ + source: 'continuing', + previousOffer: vaultOfferId, + invitationMakerName: 'AdjustBalances', +} +``` + +In this continuing offer, the smart wallet uses the `spec.previousOffer` id to look up the `.invitationMakers` property of the result of the previous offer. It uses `E(invitationMakers)[spec.invitationMakerName](...spec.invitationArgs)` to make an invitation. + ::: The client fills in the proposal, which instructs the `SmartWallet`