@agoric/fast-usdc 0.2.0-upgrade-20-dev-ef71cfd.0 → 0.2.0-upgrade-19-devnet-dev-5428c4d.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,27 +1,101 @@
1
1
  # Fast USDC
2
2
 
3
- Development package for the Fast USDC product. Here in agoric-sdk as a
4
- convenience for integration testing and iterating on the SDK affordances
5
- required for the product.
3
+ Development package for the Fast USDC product.
4
+ Here in agoric-sdk as a convenience for integration testing and iterating on the SDK affordances required for the product.
6
5
 
7
6
  # Factoring
8
7
 
9
- This package is meant to contain all the code for the Fast USDC product.
10
- However, there are some constraints:
8
+ This package is meant to contain all the code for the Fast USDC product. However there are some constraints:
11
9
 
12
- - a3p integration tests are in the `a3p-integration` top-level package, separate
13
- from this workspace
14
- - the proposal builders are in `@agoric/builders` to work with the
15
- a3p-integration `build:submissions` script
16
- - the RunUtils tests are in `@aglocal/boot` to test running them atop a fresh
17
- bootstrapped environment
10
+ - a3p integration tests are in the `a3p-integration` top-level package, separate from this workspace
11
+ - the proposal builders are in `@agoric/builders` to work with the a3p-integration `build:submissions` script
12
+ - the RunUtils tests are in `@agoric/boot` to test running them atop a fresh bootstrapped environment
18
13
 
19
14
  Over time we can update our tooling to decouple this more from the `packages` directory.
20
15
 
21
- 1. Make a3p-integration `build:submissions` script work with arbitrary builder
22
- paths, allowing this to be above `@agoric/builders` in the package graph
23
- 2. Export bootstrap testing utilities from `@aglocal/boot`, allowing this to be
24
- above `@aglocal/boot` in the package graph
25
- 3. Update CI to support packages that aren't under `packages/`, eg. a top-level
26
- `dapps` directory
16
+ 1. Make a3p-integration `build:submissions` script work with arbitrary builder paths, allowing this to be above `@agoric/builders` in the package graph
17
+ 2. Export bootstrap testing utilities from `@agoric/boot`, allowing this to be above `@agoric/boot` in the package graph
18
+ 3. Update CI to support packages that aren't under `packages/`, eg. a top-level `dapps` directory
27
19
  4. Move this package out of agoric-sdk
20
+
21
+ # Transaction feed
22
+
23
+ ## Oracles interface
24
+
25
+ Oracles run off-chain and interact with the contract via an Agoric smart wallet bridge.
26
+ ```mermaid
27
+ sequenceDiagram
28
+ title Becoming an oracle operator
29
+ participant OW as Operator N<br/>Smart Wallet
30
+ participant FUC as Fast USDC<br/>Contract Exo
31
+ participant CE as Core Eval
32
+
33
+ CE->>FUC: makeOperatorInvitation()
34
+ FUC-->>CE: operatorInvitation
35
+ CE->>+OW: deposit(operatorInvitation)
36
+
37
+ Note left of FUC: Off-chain wallet accepts the operator invitation
38
+
39
+ OW->>+FUC: offer(operatorInvitation)
40
+ FUC-->>OW: operator invitationMakers: {SubmitEvidence}
41
+
42
+ Note left of FUC: Off-chain watcher detects evidence
43
+ OW->>+FUC: offer(SubmitEvidence, evidence)
44
+ ```
45
+
46
+ ```mermaid
47
+ sequenceDiagram
48
+ title Receiving evidence
49
+ participant W as Operator N<br/>Smart Wallet
50
+ participant A as Operator N<br/>Admin Oexo
51
+ participant TF as Transaction<br/>Feed
52
+
53
+ W->>A: offer(SubmitEvidence, evidence)
54
+
55
+ Note left of A: Once 3 operators push the same…
56
+
57
+ A->>TF: notify(evidence)
58
+ ```
59
+
60
+ # Status Manager
61
+
62
+ ### Pending Advance State Diagram
63
+
64
+ *Transactions are qualified by the OCW and EventFeed before arriving to the Advancer.*
65
+
66
+ ```mermaid
67
+ stateDiagram-v2
68
+ [*] --> Observed: observe()
69
+ [*] --> Advancing: advancing()
70
+
71
+ Advancing --> Advanced: advanceOutcome(...true)
72
+ Advancing --> AdvanceFailed: advanceOutcome(...false)
73
+
74
+ Observed --> [*]: dequeueStatus()
75
+ Advanced --> [*]: dequeueStatus()
76
+ AdvanceFailed --> [*]: dequeueStatus()
77
+
78
+ note right of [*]
79
+ After dequeueStatus():
80
+ Transaction is removed
81
+ from pendingTxs store.
82
+ Settler will .disburse()
83
+ or .forward()
84
+ end note
85
+ ```
86
+
87
+ ### Complete state diagram (starting from Transaction Feed into Advancer)
88
+
89
+ ```mermaid
90
+ stateDiagram-v2
91
+ Observed --> AdvanceSkipped : Risks identified
92
+ Observed --> Advancing : No risks, can advance
93
+ Observed --> Forwarding : No risks, Mint deposited before advance
94
+ Forwarding --> Forwarded
95
+ Advancing --> Advanced
96
+ Advanced --> Disbursed
97
+ AdvanceSkipped --> Forwarding : Mint deposited
98
+ AdvanceFailed --> Forwarding : Mint deposited
99
+ Advancing --> AdvanceFailed
100
+ Forwarding --> ForwardFailed
101
+ ```
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@agoric/fast-usdc",
3
- "version": "0.2.0-upgrade-20-dev-ef71cfd.0+ef71cfd",
3
+ "version": "0.2.0-upgrade-19-devnet-dev-5428c4d.0+5428c4d",
4
4
  "description": "CLI and library for Fast USDC product",
5
5
  "type": "module",
6
6
  "files": [
7
+ "contract",
7
8
  "src",
8
9
  "tools"
9
10
  ],
@@ -22,33 +23,39 @@
22
23
  "lint:eslint": "eslint ."
23
24
  },
24
25
  "devDependencies": {
26
+ "@agoric/swingset-liveslots": "0.10.3-upgrade-19-devnet-dev-5428c4d.0+5428c4d",
27
+ "@agoric/vats": "0.16.0-upgrade-19-devnet-dev-5428c4d.0+5428c4d",
28
+ "@agoric/zone": "0.3.0-upgrade-19-devnet-dev-5428c4d.0+5428c4d",
25
29
  "@fast-check/ava": "^2.0.1",
26
30
  "ava": "^5.3.0",
27
31
  "c8": "^10.1.2",
28
- "nano-spawn": "^0.2.0",
32
+ "execa": "9.1.0",
29
33
  "ts-blank-space": "^0.4.4"
30
34
  },
31
35
  "dependencies": {
32
- "@agoric/client-utils": "0.2.0-upgrade-20-dev-ef71cfd.0+ef71cfd",
33
- "@agoric/cosmic-proto": "0.5.0-upgrade-20-dev-ef71cfd.0+ef71cfd",
34
- "@agoric/ertp": "0.16.3-upgrade-20-dev-ef71cfd.0+ef71cfd",
35
- "@agoric/internal": "0.4.0-upgrade-20-dev-ef71cfd.0+ef71cfd",
36
- "@agoric/notifier": "0.7.0-upgrade-20-dev-ef71cfd.0+ef71cfd",
37
- "@agoric/orchestration": "0.2.0-upgrade-20-dev-ef71cfd.0+ef71cfd",
38
- "@agoric/zoe": "0.27.0-upgrade-20-dev-ef71cfd.0+ef71cfd",
39
- "@cosmjs/proto-signing": "^0.33.0",
40
- "@cosmjs/stargate": "^0.33.0",
36
+ "@agoric/client-utils": "0.2.0-upgrade-19-devnet-dev-5428c4d.0+5428c4d",
37
+ "@agoric/cosmic-proto": "0.5.0-upgrade-19-devnet-dev-5428c4d.0+5428c4d",
38
+ "@agoric/ertp": "0.16.3-upgrade-19-devnet-dev-5428c4d.0+5428c4d",
39
+ "@agoric/internal": "0.4.0-upgrade-19-devnet-dev-5428c4d.0+5428c4d",
40
+ "@agoric/notifier": "0.7.0-upgrade-19-devnet-dev-5428c4d.0+5428c4d",
41
+ "@agoric/orchestration": "0.2.0-upgrade-19-devnet-dev-5428c4d.0+5428c4d",
42
+ "@agoric/store": "0.9.3-upgrade-19-devnet-dev-5428c4d.0+5428c4d",
43
+ "@agoric/vat-data": "0.5.3-upgrade-19-devnet-dev-5428c4d.0+5428c4d",
44
+ "@agoric/vow": "0.2.0-upgrade-19-devnet-dev-5428c4d.0+5428c4d",
45
+ "@agoric/zoe": "0.27.0-upgrade-19-devnet-dev-5428c4d.0+5428c4d",
46
+ "@cosmjs/proto-signing": "^0.32.4",
47
+ "@cosmjs/stargate": "^0.32.4",
41
48
  "@endo/base64": "^1.0.9",
42
- "@endo/common": "^1.2.10",
43
- "@endo/errors": "^1.2.10",
44
- "@endo/eventual-send": "^1.3.1",
45
- "@endo/far": "^1.1.11",
46
- "@endo/init": "^1.1.9",
47
- "@endo/marshal": "^1.6.4",
48
- "@endo/nat": "^5.1.0",
49
- "@endo/pass-style": "^1.5.0",
50
- "@endo/patterns": "^1.5.0",
51
- "@endo/promise-kit": "^1.1.10",
49
+ "@endo/common": "^1.2.9",
50
+ "@endo/errors": "^1.2.9",
51
+ "@endo/eventual-send": "^1.3.0",
52
+ "@endo/far": "^1.1.10",
53
+ "@endo/init": "^1.1.8",
54
+ "@endo/marshal": "^1.6.3",
55
+ "@endo/nat": "^5.0.14",
56
+ "@endo/pass-style": "^1.4.8",
57
+ "@endo/patterns": "^1.4.8",
58
+ "@endo/promise-kit": "^1.1.9",
52
59
  "@nick134-bit/noblejs": "0.0.2",
53
60
  "bech32": "^2.0.0",
54
61
  "commander": "^12.1.0",
@@ -75,5 +82,5 @@
75
82
  "publishConfig": {
76
83
  "access": "public"
77
84
  },
78
- "gitHead": "ef71cfdc9e62572cab9a3d2821dc446ce0d700c3"
85
+ "gitHead": "5428c4da67b53cef7ff53ba7b2a28cf6ec8f643a"
79
86
  }
@@ -0,0 +1,63 @@
1
+ import { makeTracer } from '@agoric/internal';
2
+ import { inviteOracles } from './utils/core-eval.js';
3
+
4
+ /**
5
+ * @import {ManifestBundleRef} from '@agoric/deploy-script-support/src/externalTypes.js'
6
+ * @import {BootstrapManifest} from '@agoric/vats/src/core/lib-boot.js'
7
+ * @import {LegibleCapData} from './utils/config-marshal.js'
8
+ * @import {FastUSDCConfig} from './types.js'
9
+ * @import {FastUSDCCorePowers, FastUSDCKit} from './start-fast-usdc.core.js';
10
+ */
11
+
12
+ const trace = makeTracer('FUSD-AddOperators', true);
13
+
14
+ /**
15
+ * @throws if oracle smart wallets are not yet provisioned
16
+ *
17
+ * @param {BootstrapPowers & FastUSDCCorePowers } powers
18
+ * @param {{ options: LegibleCapData<FastUSDCConfig> }} config
19
+ */
20
+ export const addOperators = async (
21
+ { consume: { namesByAddress, fastUsdcKit } },
22
+ config,
23
+ ) => {
24
+ trace(addOperators.name);
25
+
26
+ const kit = await fastUsdcKit;
27
+
28
+ const { creatorFacet } = kit;
29
+
30
+ trace(config);
31
+
32
+ // @ts-expect-error XXX LegibleCapData typedef
33
+ const { oracles } = config.options.structure;
34
+
35
+ await inviteOracles({ creatorFacet, namesByAddress }, oracles);
36
+ };
37
+ harden(addOperators);
38
+
39
+ /**
40
+ * @param {{
41
+ * restoreRef: (b: ERef<ManifestBundleRef>) => Promise<Installation>;
42
+ * }} utils
43
+ * @param {{
44
+ * options: LegibleCapData<FastUSDCConfig>;
45
+ * }} param1
46
+ */
47
+ export const getManifestForAddOperators = ({ restoreRef: _ }, { options }) => {
48
+ return {
49
+ /** @type {BootstrapManifest} */
50
+ manifest: {
51
+ [addOperators.name]: {
52
+ consume: {
53
+ fastUsdcKit: true,
54
+
55
+ // widely shared: name services
56
+ agoricNames: true,
57
+ namesByAddress: true,
58
+ },
59
+ },
60
+ },
61
+ options,
62
+ };
63
+ };
package/src/cli/config.js CHANGED
@@ -23,7 +23,7 @@ import { stdin as input, stdout as output } from 'node:process';
23
23
  }} ConfigOpts
24
24
  */
25
25
 
26
- /** @import { File } from './util/file.js' */
26
+ /** @import { File } from './util/file' */
27
27
 
28
28
  export const init = async (
29
29
  /** @type {File} */ configFile,
@@ -18,7 +18,7 @@ import {
18
18
  floorDivideBy,
19
19
  multiplyBy,
20
20
  parseRatio,
21
- } from '@agoric/ertp/src/ratio.js';
21
+ } from '@agoric/zoe/src/contractSupport/ratio.js';
22
22
  import { InvalidArgumentError } from 'commander';
23
23
  import { outputActionAndHint } from './bridge-action.js';
24
24
  import { Offers } from '../clientSupport.js';
@@ -38,7 +38,7 @@ const parseDecimal = arg => {
38
38
 
39
39
  /**
40
40
  * @param {string} amountString
41
- * @param {Brand<'nat'>} usdc
41
+ * @param {Brand} usdc
42
42
  */
43
43
  const parseUSDCAmount = (amountString, usdc) => {
44
44
  const USDC_DECIMALS = 6;
@@ -3,6 +3,7 @@
3
3
  * @import {Command} from 'commander';
4
4
  * @import {OfferSpec} from '@agoric/smart-wallet/src/offers.js';
5
5
  * @import {ExecuteOfferAction} from '@agoric/smart-wallet/src/smartWallet.js';
6
+ * @import {OperatorKit} from '../exos/operator-kit.js';
6
7
  */
7
8
 
8
9
  import {
@@ -12,7 +13,7 @@ import {
12
13
  import { mustMatch } from '@agoric/internal';
13
14
  import { Nat } from '@endo/nat';
14
15
  import { InvalidArgumentError } from 'commander';
15
- import { INVITATION_MAKERS_DESC } from '../operator-kit-interface.js';
16
+ import { INVITATION_MAKERS_DESC } from '../exos/transaction-feed.js';
16
17
  import { CctpTxEvidenceShape } from '../type-guards.js';
17
18
  import { outputActionAndHint } from './bridge-action.js';
18
19
 
@@ -127,7 +128,9 @@ export const addOperatorCommands = (
127
128
  invitationSpec: {
128
129
  source: 'continuing',
129
130
  previousOffer: previousOfferId,
131
+ /** @type {string & keyof OperatorKit['invitationMakers'] } */
130
132
  invitationMakerName: 'SubmitEvidence',
133
+ /** @type {Parameters<OperatorKit['invitationMakers']['SubmitEvidence']> } */
131
134
  invitationArgs: [evidence],
132
135
  },
133
136
  proposal: {},
@@ -16,7 +16,7 @@ import {
16
16
  } from './util/noble.js';
17
17
  import { queryUSDCBalance } from './util/bank.js';
18
18
 
19
- /** @import { File } from './util/file.js' */
19
+ /** @import { File } from './util/file' */
20
20
  /** @import { VStorage } from '@agoric/client-utils' */
21
21
  /** @import { SigningStargateClient } from '@cosmjs/stargate' */
22
22
  /** @import { JsonRpcProvider as ethProvider } from 'ethers' */
@@ -34,7 +34,7 @@ const transfer = async (
34
34
  setTimeout = globalThis.setTimeout,
35
35
  ) => {
36
36
  const execute = async (
37
- /** @type {import('./config.js').ConfigOpts} */ config,
37
+ /** @type {import('./config').ConfigOpts} */ config,
38
38
  ) => {
39
39
  const netConfig = await fetchEnvNetworkConfig({ env, fetch });
40
40
  vstorage ||= makeVStorage(
package/src/constants.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Status values for FastUSDC. Includes states for advancing and settling.
2
+ * Status values for FastUSDC.
3
3
  *
4
4
  * @enum {(typeof TxStatus)[keyof typeof TxStatus]}
5
5
  */
@@ -31,7 +31,7 @@ export const TerminalTxStatus = {
31
31
  };
32
32
 
33
33
  /**
34
- * Status values for the StatusManager while an advance is being processed.
34
+ * Status values for the StatusManager.
35
35
  *
36
36
  * @enum {(typeof PendingTxStatus)[keyof typeof PendingTxStatus]}
37
37
  */
@@ -0,0 +1,93 @@
1
+ /** @file core eval module to collect fees. */
2
+ import { AmountMath } from '@agoric/ertp';
3
+ import { floorMultiplyBy } from '@agoric/zoe/src/contractSupport/index.js';
4
+ import { E } from '@endo/far';
5
+ import { makeTracer } from '@agoric/internal';
6
+ import { fromExternalConfig } from './utils/config-marshal.js';
7
+
8
+ /**
9
+ * @import {DepositFacet} from '@agoric/ertp';
10
+ * @import {FastUSDCCorePowers} from '@agoric/fast-usdc/src/start-fast-usdc.core.js';
11
+ * @import {CopyRecord} from '@endo/pass-style'
12
+ * @import {BootstrapManifestPermit} from '@agoric/vats/src/core/lib-boot.js'
13
+ * @import {LegibleCapData} from './utils/config-marshal.js'
14
+ */
15
+
16
+ /**
17
+ * @typedef {{ destinationAddress: string } &
18
+ * ({ feePortion: Ratio} | {fixedFees: Amount<'nat'>}) &
19
+ * CopyRecord
20
+ * } FeeDistributionTerms
21
+ */
22
+
23
+ const kwUSDC = 'USDC'; // keyword in AmountKeywordRecord
24
+ const issUSDC = 'USDC'; // issuer name
25
+
26
+ const trace = makeTracer('FUCF', true);
27
+
28
+ /**
29
+ * @param {BootstrapPowers & FastUSDCCorePowers } permittedPowers
30
+ * @param {{ options: LegibleCapData<{ feeTerms: FeeDistributionTerms}> }} config
31
+ */
32
+ export const distributeFees = async (permittedPowers, config) => {
33
+ trace('distributeFees...', config.options);
34
+
35
+ const { agoricNames, namesByAddress, zoe } = permittedPowers.consume;
36
+ /** @type {Brand<'nat'>} */
37
+ const usdcBrand = await E(agoricNames).lookup('brand', issUSDC);
38
+ /** @type {{ feeTerms: FeeDistributionTerms}} */
39
+ const { feeTerms: terms } = fromExternalConfig(config.options, {
40
+ USDC: usdcBrand,
41
+ });
42
+
43
+ const { creatorFacet } = await permittedPowers.consume.fastUsdcKit;
44
+ const want = {
45
+ [kwUSDC]: await ('fixedFees' in terms
46
+ ? terms.fixedFees
47
+ : E(creatorFacet)
48
+ .getContractFeeBalance()
49
+ .then(balance => floorMultiplyBy(balance, terms.feePortion))),
50
+ };
51
+ const proposal = harden({ want });
52
+
53
+ /** @type {DepositFacet} */
54
+ const depositFacet = await E(namesByAddress).lookup(
55
+ terms.destinationAddress,
56
+ 'depositFacet',
57
+ );
58
+ trace('to:', terms.destinationAddress, depositFacet);
59
+
60
+ const toWithdraw = await E(creatorFacet).makeWithdrawFeesInvitation();
61
+ trace('invitation:', toWithdraw, 'proposal:', proposal);
62
+ const seat = E(zoe).offer(toWithdraw, proposal);
63
+ const result = await E(seat).getOfferResult();
64
+ trace('offer result', result);
65
+ const payout = await E(seat).getPayout(kwUSDC);
66
+ /** @type {Amount<'nat'>} */
67
+ // @ts-expect-error USDC is a nat brand
68
+ const rxd = await E(depositFacet).receive(payout);
69
+ trace('received', rxd);
70
+ if (!AmountMath.isGTE(rxd, proposal.want[kwUSDC])) {
71
+ trace('🚨 expected', proposal.want[kwUSDC], 'got', rxd);
72
+ }
73
+ trace('done');
74
+ };
75
+ harden(distributeFees);
76
+
77
+ /** @satisfies {BootstrapManifestPermit} */
78
+ const permit = {
79
+ consume: {
80
+ fastUsdcKit: true,
81
+ agoricNames: true,
82
+ namesByAddress: true,
83
+ zoe: true,
84
+ },
85
+ };
86
+
87
+ /**
88
+ * @param {unknown} _utils
89
+ * @param {Parameters<typeof distributeFees>[1]} config
90
+ */
91
+ export const getManifestForDistributeFees = (_utils, { options }) => {
92
+ return { manifest: { [distributeFees.name]: permit }, options };
93
+ };