Skip to content

Commit b22f9cb

Browse files
authored
Merge pull request #246 from Agoric/mk/add-fusdc-cctp-beta
feat: add fast-usdc-cctp-beta proposal
2 parents b1c33b3 + 3646d73 commit b22f9cb

12 files changed

+5987
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nodeLinker: node-modules
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# proposal for deploying the beta CCTP release of Fast USDC
2+
3+
See https://github.com/Agoric/agoric-sdk/releases/tag/fast-usdc-cctp-b1 for release notes.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"agoricProposal": {
3+
"type": "/agoric.swingset.CoreEvalProposal",
4+
"releaseNotes": "https://github.com/Agoric/agoric-sdk/releases/tag/fast-usdc-cctp-b1"
5+
},
6+
"type": "module",
7+
"license": "Apache-2.0",
8+
"dependencies": {
9+
"@agoric/client-utils": "dev",
10+
"@agoric/fast-usdc": "dev",
11+
"@agoric/synthetic-chain": "0.5.5",
12+
"@endo/init": "^1.1.9",
13+
"agoric": "dev",
14+
"ava": "^5.3.1"
15+
},
16+
"ava": {
17+
"concurrency": 1,
18+
"timeout": "2m",
19+
"files": [
20+
"test/**/*.test.*",
21+
"!submission"
22+
]
23+
},
24+
"scripts": {
25+
"agops": "yarn --cwd /usr/src/agoric-sdk/ agops"
26+
},
27+
"packageManager": "[email protected]"
28+
}

proposals/94:fast-usdc-cctp-beta/submission/b1-57337cfe14b7313808db4f60b65ac24849aaee9b3267d197dbb13e34b2bbb98851a49d2e9ae815dbbb6797af645231752b8db7e9c9587d1c20c790e4c808456c.json

Lines changed: 5 additions & 0 deletions
Large diffs are not rendered by default.

proposals/94:fast-usdc-cctp-beta/submission/b1-9d3c89aa07f23338ca990bc2dba3f05d6de7a1bbbce6b2228070df6220b53627ba0a630b7fc16edbf36ff514f9801540f799a4ea68158a8b708ed6b4eb0ccd36.json

Lines changed: 5 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"consume": {
3+
"fastUsdcKit": true,
4+
"agoricNamesAdmin": "makeCoreProposalBehavior",
5+
"vatAdminSvc": "makeCoreProposalBehavior",
6+
"zoe": "makeCoreProposalBehavior"
7+
},
8+
"evaluateBundleCap": "makeCoreProposalBehavior",
9+
"installation": {
10+
"produce": "makeCoreProposalBehavior"
11+
},
12+
"modules": {
13+
"utils": {
14+
"runModuleBehaviors": "makeCoreProposalBehavior"
15+
}
16+
}
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "eval-fast-usdc-evm-dests",
3+
"script": "eval-fast-usdc-evm-dests.js",
4+
"permit": "eval-fast-usdc-evm-dests-permit.json",
5+
"bundles": [
6+
{
7+
"entrypoint": "@aglocal/fast-usdc-deploy/dist/fast-usdc.contract.bundle.js",
8+
"bundleID": "b1-57337cfe14b7313808db4f60b65ac24849aaee9b3267d197dbb13e34b2bbb98851a49d2e9ae815dbbb6797af645231752b8db7e9c9587d1c20c790e4c808456c",
9+
"fileName": "/Users/mujahid/.agoric/cache/b1-57337cfe14b7313808db4f60b65ac24849aaee9b3267d197dbb13e34b2bbb98851a49d2e9ae815dbbb6797af645231752b8db7e9c9587d1c20c790e4c808456c.json"
10+
},
11+
{
12+
"entrypoint": "./upgrade-evm-dests.core.js",
13+
"bundleID": "b1-9d3c89aa07f23338ca990bc2dba3f05d6de7a1bbbce6b2228070df6220b53627ba0a630b7fc16edbf36ff514f9801540f799a4ea68158a8b708ed6b4eb0ccd36",
14+
"fileName": "/Users/mujahid/.agoric/cache/b1-9d3c89aa07f23338ca990bc2dba3f05d6de7a1bbbce6b2228070df6220b53627ba0a630b7fc16edbf36ff514f9801540f799a4ea68158a8b708ed6b4eb0ccd36.json"
15+
}
16+
]
17+
}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// This is generated by writeCoreEval; please edit!
2+
/* eslint-disable */
3+
4+
const manifestBundleRef = {
5+
bundleID:
6+
'b1-9d3c89aa07f23338ca990bc2dba3f05d6de7a1bbbce6b2228070df6220b53627ba0a630b7fc16edbf36ff514f9801540f799a4ea68158a8b708ed6b4eb0ccd36',
7+
};
8+
const getManifestCall = harden([
9+
'getManifestForUpgradeEvmDests',
10+
{
11+
installKeys: {
12+
fastUsdc: {
13+
bundleID:
14+
'b1-57337cfe14b7313808db4f60b65ac24849aaee9b3267d197dbb13e34b2bbb98851a49d2e9ae815dbbb6797af645231752b8db7e9c9587d1c20c790e4c808456c',
15+
},
16+
},
17+
options: {},
18+
},
19+
]);
20+
const customManifest = {
21+
upgradeEvmDests: {
22+
consume: {
23+
fastUsdcKit: true,
24+
},
25+
},
26+
};
27+
28+
// Make a behavior function and "export" it by way of script completion value.
29+
// It is constructed by an anonymous invocation to ensure the absence of a global binding
30+
// for makeCoreProposalBehavior, which may not be necessary but preserves behavior pre-dating
31+
// https://github.com/Agoric/agoric-sdk/pull/8712 .
32+
const behavior = (({
33+
manifestBundleRef,
34+
getManifestCall: [manifestGetterName, ...manifestGetterArgs],
35+
customManifest,
36+
E,
37+
log = console.info,
38+
customRestoreRef,
39+
}) => {
40+
const { entries, fromEntries } = Object;
41+
42+
/**
43+
* Given an object whose properties may be promise-valued, return a promise
44+
* for an analogous object in which each such value has been replaced with its
45+
* fulfillment.
46+
* This is a non-recursive form of endo `deeplyFulfilled`.
47+
*
48+
* @template T
49+
* @param {{[K in keyof T]: (T[K] | Promise<T[K]>)}} obj
50+
* @returns {Promise<T>}
51+
*/
52+
const shallowlyFulfilled = async obj => {
53+
if (!obj) {
54+
return obj;
55+
}
56+
const awaitedEntries = await Promise.all(
57+
entries(obj).map(async ([key, valueP]) => {
58+
const value = await valueP;
59+
return [key, value];
60+
}),
61+
);
62+
return fromEntries(awaitedEntries);
63+
};
64+
65+
const makeRestoreRef = (vatAdminSvc, zoe) => {
66+
/** @type {(ref: import\('./externalTypes.js').ManifestBundleRef) => Promise<Installation<unknown>>} */
67+
const defaultRestoreRef = async bundleRef => {
68+
// extract-proposal.js creates these records, and bundleName is
69+
// the optional name under which the bundle was installed into
70+
// config.bundles
71+
const bundleIdP =
72+
'bundleName' in bundleRef
73+
? E(vatAdminSvc).getBundleIDByName(bundleRef.bundleName)
74+
: bundleRef.bundleID;
75+
const bundleID = await bundleIdP;
76+
const label = bundleID.slice(0, 8);
77+
return E(zoe).installBundleID(bundleID, label);
78+
};
79+
return defaultRestoreRef;
80+
};
81+
82+
/** @param {ChainBootstrapSpace & BootstrapPowers & { evaluateBundleCap: any }} powers */
83+
const coreProposalBehavior = async powers => {
84+
// NOTE: `powers` is expected to match or be a superset of the above `permits` export,
85+
// which should therefore be kept in sync with this deconstruction code.
86+
// HOWEVER, do note that this function is invoked with at least the *union* of powers
87+
// required by individual moduleBehaviors declared by the manifest getter, which is
88+
// necessary so it can use `runModuleBehaviors` to provide the appropriate subset to
89+
// each one (see ./writeCoreEvalParts.js).
90+
// Handle `powers` with the requisite care.
91+
const {
92+
consume: { vatAdminSvc, zoe, agoricNamesAdmin },
93+
evaluateBundleCap,
94+
installation: { produce: produceInstallations },
95+
modules: {
96+
utils: { runModuleBehaviors },
97+
},
98+
} = powers;
99+
100+
// Get the on-chain installation containing the manifest and behaviors.
101+
log('evaluateBundleCap', {
102+
manifestBundleRef,
103+
manifestGetterName,
104+
vatAdminSvc,
105+
});
106+
let bcapP;
107+
if ('bundleName' in manifestBundleRef) {
108+
bcapP = E(vatAdminSvc).getNamedBundleCap(manifestBundleRef.bundleName);
109+
} else if ('bundleID' in manifestBundleRef) {
110+
bcapP = E(vatAdminSvc).getBundleCap(manifestBundleRef.bundleID);
111+
} else {
112+
const keys = Reflect.ownKeys(manifestBundleRef).map(key =>
113+
typeof key === 'string' ? JSON.stringify(key) : String(key),
114+
);
115+
const keysStr = `[${keys.join(', ')}]`;
116+
throw Error(
117+
`bundleRef must have own bundleName or bundleID, missing in ${keysStr}`,
118+
);
119+
}
120+
const bundleCap = await bcapP;
121+
122+
const proposalNS = await evaluateBundleCap(bundleCap);
123+
124+
// Get the manifest and its metadata.
125+
log('execute', {
126+
manifestGetterName,
127+
bundleExports: Object.keys(proposalNS),
128+
});
129+
const restoreRef = customRestoreRef || makeRestoreRef(vatAdminSvc, zoe);
130+
const {
131+
manifest,
132+
options: rawOptions,
133+
installations: rawInstallations,
134+
} = await proposalNS[manifestGetterName](
135+
harden({ restoreRef }),
136+
...manifestGetterArgs,
137+
);
138+
139+
// Await promises in the returned options and installations records.
140+
const [options, installations] = await Promise.all(
141+
[rawOptions, rawInstallations].map(shallowlyFulfilled),
142+
);
143+
144+
// Publish the installations for our dependencies.
145+
const installationEntries = entries(installations || {});
146+
if (installationEntries.length > 0) {
147+
const installAdmin = E(agoricNamesAdmin).lookupAdmin('installation');
148+
await Promise.all(
149+
installationEntries.map(([key, value]) => {
150+
produceInstallations[key].reset();
151+
produceInstallations[key].resolve(value);
152+
return E(installAdmin).update(key, value);
153+
}),
154+
);
155+
}
156+
157+
// Evaluate the manifest.
158+
return runModuleBehaviors({
159+
// Remember that `powers` may be arbitrarily broad.
160+
allPowers: powers,
161+
behaviors: proposalNS,
162+
manifest: customManifest || manifest,
163+
makeConfig: (name, _permit) => {
164+
log('coreProposal:', name);
165+
return { options };
166+
},
167+
});
168+
};
169+
170+
return coreProposalBehavior;
171+
})({ manifestBundleRef, getManifestCall, customManifest, E });
172+
behavior;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
# segregate so changing these does not invalidate the proposal image
5+
# à la https://github.com/Agoric/agoric-3-proposals/pull/213
6+
cd test
7+
8+
yarn ava
9+
10+
./test-cli.sh
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// @ts-check
2+
/* eslint-env node */
3+
import '@endo/init/legacy.js'; // axios compat
4+
5+
import { LOCAL_CONFIG, makeSmartWalletKit } from '@agoric/client-utils';
6+
import test from 'ava';
7+
import { getIncarnation } from '@agoric/synthetic-chain';
8+
9+
const io = {
10+
delay: ms => new Promise(resolve => setTimeout(() => resolve(undefined), ms)),
11+
fetch: global.fetch,
12+
};
13+
14+
test('accounts', async t => {
15+
const swk = await makeSmartWalletKit(io, LOCAL_CONFIG);
16+
17+
// XXX readPublished once it can handle plain JSON
18+
const nodeStr = await swk.vstorage.readLatest('published.fastUsdc');
19+
const { values } = JSON.parse(JSON.parse(nodeStr).value);
20+
const { poolAccount, settlementAccount } = JSON.parse(values[0]);
21+
22+
// exact addresses are not available at design time
23+
t.true(poolAccount.startsWith('agoric1'));
24+
t.true(settlementAccount.startsWith('agoric1'));
25+
});
26+
27+
test(`fastUsdc incarnation reflects cctp`, async t => {
28+
const history = { beta: 0, rc1: 1, gtm: 2, cctp: 3 };
29+
t.is(await getIncarnation('fastUsdc'), history.cctp);
30+
});
31+
32+
test('feedPolicy updated for GTM', async t => {
33+
const swk = await makeSmartWalletKit(io, LOCAL_CONFIG);
34+
35+
const policy = await swk.readPublished('fastUsdc.feedPolicy');
36+
t.log('policy', policy);
37+
t.like(policy, {
38+
chainPolicies: {
39+
Arbitrum: {
40+
confirmations: 96, // was 2 in Beta
41+
},
42+
},
43+
});
44+
});
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
# XXX the from address is gov1 but using that causes:
5+
# Error: gov1 is not a valid name or address: decoding bech32 failed: invalid bech32 string length 4
6+
# Usage:
7+
# agd keys show [name_or_address [name_or_address...]] [flags]
8+
9+
echo CLI test accepting operator invitation
10+
ACCEPT_OFFER_ID=fastUsdcTestAccept
11+
yarn fast-usdc operator accept --offerId $ACCEPT_OFFER_ID >| accept.json
12+
cat accept.json
13+
yarn agoric wallet send --offer accept.json --from agoric1ee9hr0jyrxhy999y755mp862ljgycmwyp4pl7q --keyring-backend test
14+
# UNTIL https://github.com/Agoric/agoric-sdk/issues/10891
15+
# ACCEPT_OFFER_ID=$(agoric wallet extract-id --offer accept.json)
16+
17+
yarn fast-usdc operator attest --previousOfferId="$ACCEPT_OFFER_ID" --forwardingChannel=foo --recipientAddress=agoric1foo --blockHash=0xfoo --blockNumber=1 --blockTimestamp=1632340000 --chainId=3 --amount=123 --forwardingAddress=noble1foo --sender 0xfoo --txHash=0xtx >| attest.json
18+
cat attest.json
19+
yarn agoric wallet send --offer attest.json --from agoric1ee9hr0jyrxhy999y755mp862ljgycmwyp4pl7q --keyring-backend test
20+
21+
# The data above are bogus and result in errors in the logs:
22+
# SwingSet: vat: v72: ----- TxFeed.11 8 publishing evidence { aux: { forwardingChannel: 'foo', recipientAddress: 'agoric1foo' }, blockHash: '0xfoo', blockNumber: 1n, chainId: 3, tx: { amount: 123n, forwardingAddress: 'noble1foo', sender: '0xfoo' }, txHash: '0xtx' } []
23+
# SwingSet: vat: v72: ----- Advancer.15 2 Advancer error: (Error#4)
24+
# SwingSet: vat: v72: Error#4: Data too short

0 commit comments

Comments
 (0)