@agoric/fast-usdc 0.1.1-other-dev-3eb1a1d.0 → 0.1.1-upgrade-19-dev-c605745.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 +43 -0
- package/package.json +29 -25
- package/src/add-operators.core.js +63 -0
- package/src/cli/bridge-action.js +40 -0
- package/src/cli/cli.js +46 -153
- package/src/cli/config-commands.js +108 -0
- package/src/cli/config.js +15 -9
- package/src/cli/lp-commands.js +160 -0
- package/src/cli/operator-commands.js +146 -0
- package/src/cli/transfer.js +63 -13
- package/src/{util → cli/util}/agoric.js +1 -1
- package/src/cli/util/bank.js +12 -0
- package/src/{util → cli/util}/cctp.js +1 -1
- package/src/{util → cli/util}/file.js +1 -1
- package/src/clientSupport.js +98 -0
- package/src/constants.js +25 -2
- package/src/distribute-fees.core.js +93 -0
- package/src/exos/advancer.js +220 -106
- package/src/exos/liquidity-pool.js +130 -81
- package/src/exos/operator-kit.js +16 -12
- package/src/exos/settler.js +360 -64
- package/src/exos/status-manager.js +316 -65
- package/src/exos/transaction-feed.js +121 -42
- package/src/fast-usdc-policy.core.js +65 -0
- package/src/fast-usdc.contract.js +165 -84
- package/src/fast-usdc.flows.js +10 -0
- package/src/main.js +1 -0
- package/src/pool-share-math.js +55 -9
- package/src/{fast-usdc.start.js → start-fast-usdc.core.js} +48 -86
- package/src/type-guards.js +75 -24
- package/src/types.ts +89 -14
- package/src/utils/chain-policies.js +140 -0
- package/src/utils/core-eval.js +73 -0
- package/src/utils/deploy-config.js +127 -0
- package/src/utils/fees.js +3 -4
- package/tools/cli-tools.ts +9 -0
- package/tools/mock-io.ts +14 -0
- package/src/exos/README.md +0 -26
- package/src/utils/address.js +0 -71
- /package/src/{util → cli/util}/noble.js +0 -0
|
@@ -1,28 +1,40 @@
|
|
|
1
1
|
import { makeTracer } from '@agoric/internal';
|
|
2
2
|
import { prepareDurablePublishKit } from '@agoric/notifier';
|
|
3
|
-
import { M } from '@endo/patterns';
|
|
4
|
-
import {
|
|
3
|
+
import { keyEQ, M } from '@endo/patterns';
|
|
4
|
+
import { Fail, quote } from '@endo/errors';
|
|
5
|
+
import { CctpTxEvidenceShape, RiskAssessmentShape } from '../type-guards.js';
|
|
5
6
|
import { defineInertInvitation } from '../utils/zoe.js';
|
|
6
7
|
import { prepareOperatorKit } from './operator-kit.js';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* @import {Zone} from '@agoric/zone';
|
|
11
|
+
* @import {MapStore} from '@agoric/store';
|
|
10
12
|
* @import {OperatorKit} from './operator-kit.js';
|
|
11
|
-
* @import {CctpTxEvidence} from '../types.js';
|
|
13
|
+
* @import {CctpTxEvidence, EvidenceWithRisk, RiskAssessment} from '../types.js';
|
|
12
14
|
*/
|
|
13
15
|
|
|
14
16
|
const trace = makeTracer('TxFeed', true);
|
|
15
17
|
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {Pick<OperatorKit, 'invitationMakers' | 'operator'>} OperatorOfferResult
|
|
20
|
+
*/
|
|
21
|
+
|
|
16
22
|
/** Name in the invitation purse (keyed also by this contract instance) */
|
|
17
23
|
export const INVITATION_MAKERS_DESC = 'oracle operator invitation';
|
|
18
24
|
|
|
19
25
|
const TransactionFeedKitI = harden({
|
|
20
26
|
operatorPowers: M.interface('Transaction Feed Admin', {
|
|
21
|
-
|
|
27
|
+
attest: M.call(
|
|
28
|
+
CctpTxEvidenceShape,
|
|
29
|
+
RiskAssessmentShape,
|
|
30
|
+
M.string(),
|
|
31
|
+
).returns(),
|
|
22
32
|
}),
|
|
23
33
|
creator: M.interface('Transaction Feed Creator', {
|
|
24
|
-
|
|
25
|
-
|
|
34
|
+
initOperator: M.call(M.string()).returns({
|
|
35
|
+
invitationMakers: M.remotable(),
|
|
36
|
+
operator: M.remotable(),
|
|
37
|
+
}),
|
|
26
38
|
makeOperatorInvitation: M.call(M.string()).returns(M.promise()),
|
|
27
39
|
removeOperator: M.call(M.string()).returns(),
|
|
28
40
|
}),
|
|
@@ -31,6 +43,28 @@ const TransactionFeedKitI = harden({
|
|
|
31
43
|
}),
|
|
32
44
|
});
|
|
33
45
|
|
|
46
|
+
/**
|
|
47
|
+
* @param {MapStore<string, RiskAssessment>[]} riskStores
|
|
48
|
+
* @param {string} txHash
|
|
49
|
+
*/
|
|
50
|
+
const allRisksIdentified = (riskStores, txHash) => {
|
|
51
|
+
/** @type {Set<string>} */
|
|
52
|
+
const setOfRisks = new Set();
|
|
53
|
+
for (const store of riskStores) {
|
|
54
|
+
const next = store.get(txHash);
|
|
55
|
+
for (const risk of next.risksIdentified ?? []) {
|
|
56
|
+
setOfRisks.add(risk);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return [...setOfRisks.values()].sort();
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const stateShape = {
|
|
63
|
+
operators: M.remotable(),
|
|
64
|
+
pending: M.remotable(),
|
|
65
|
+
risks: M.remotable(),
|
|
66
|
+
};
|
|
67
|
+
|
|
34
68
|
/**
|
|
35
69
|
* @param {Zone} zone
|
|
36
70
|
* @param {ZCF} zcf
|
|
@@ -41,7 +75,7 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
|
|
|
41
75
|
kinds,
|
|
42
76
|
'Transaction Feed',
|
|
43
77
|
);
|
|
44
|
-
/** @type {PublishKit<
|
|
78
|
+
/** @type {PublishKit<EvidenceWithRisk>} */
|
|
45
79
|
const { publisher, subscriber } = makeDurablePublishKit();
|
|
46
80
|
|
|
47
81
|
const makeInertInvitation = defineInertInvitation(zcf, 'submitting evidence');
|
|
@@ -55,14 +89,12 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
|
|
|
55
89
|
TransactionFeedKitI,
|
|
56
90
|
() => {
|
|
57
91
|
/** @type {MapStore<string, OperatorKit>} */
|
|
58
|
-
const operators = zone.mapStore('operators'
|
|
59
|
-
durable: true,
|
|
60
|
-
});
|
|
92
|
+
const operators = zone.mapStore('operators');
|
|
61
93
|
/** @type {MapStore<string, MapStore<string, CctpTxEvidence>>} */
|
|
62
|
-
const pending = zone.mapStore('pending'
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return { operators, pending };
|
|
94
|
+
const pending = zone.mapStore('pending');
|
|
95
|
+
/** @type {MapStore<string, MapStore<string, RiskAssessment>>} */
|
|
96
|
+
const risks = zone.mapStore('risks');
|
|
97
|
+
return { operators, pending, risks };
|
|
66
98
|
},
|
|
67
99
|
{
|
|
68
100
|
creator: {
|
|
@@ -72,14 +104,14 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
|
|
|
72
104
|
* CCTP transactions.
|
|
73
105
|
*
|
|
74
106
|
* @param {string} operatorId unique per contract instance
|
|
75
|
-
* @returns {Promise<Invitation<
|
|
107
|
+
* @returns {Promise<Invitation<OperatorOfferResult>>}
|
|
76
108
|
*/
|
|
77
109
|
makeOperatorInvitation(operatorId) {
|
|
78
110
|
const { creator } = this.facets;
|
|
79
111
|
trace('makeOperatorInvitation', operatorId);
|
|
80
112
|
|
|
81
113
|
return zcf.makeInvitation(
|
|
82
|
-
/** @type {OfferHandler<
|
|
114
|
+
/** @type {OfferHandler<OperatorOfferResult>} */
|
|
83
115
|
seat => {
|
|
84
116
|
seat.exit();
|
|
85
117
|
return creator.initOperator(operatorId);
|
|
@@ -87,9 +119,12 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
|
|
|
87
119
|
INVITATION_MAKERS_DESC,
|
|
88
120
|
);
|
|
89
121
|
},
|
|
90
|
-
/**
|
|
122
|
+
/**
|
|
123
|
+
* @param {string} operatorId
|
|
124
|
+
* @returns {OperatorOfferResult}
|
|
125
|
+
*/
|
|
91
126
|
initOperator(operatorId) {
|
|
92
|
-
const { operators, pending } = this.state;
|
|
127
|
+
const { operators, pending, risks } = this.state;
|
|
93
128
|
trace('initOperator', operatorId);
|
|
94
129
|
|
|
95
130
|
const operatorKit = makeOperatorKit(
|
|
@@ -101,12 +136,18 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
|
|
|
101
136
|
operatorId,
|
|
102
137
|
zone.detached().mapStore('pending evidence'),
|
|
103
138
|
);
|
|
139
|
+
risks.init(operatorId, zone.detached().mapStore('risk assessments'));
|
|
104
140
|
|
|
105
|
-
|
|
141
|
+
// Subset facets to all the off-chain operator needs
|
|
142
|
+
const { invitationMakers, operator } = operatorKit;
|
|
143
|
+
return {
|
|
144
|
+
invitationMakers,
|
|
145
|
+
operator,
|
|
146
|
+
};
|
|
106
147
|
},
|
|
107
148
|
|
|
108
149
|
/** @param {string} operatorId */
|
|
109
|
-
|
|
150
|
+
removeOperator(operatorId) {
|
|
110
151
|
const { operators } = this.state;
|
|
111
152
|
trace('removeOperator', operatorId);
|
|
112
153
|
const operatorKit = operators.get(operatorId);
|
|
@@ -118,23 +159,17 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
|
|
|
118
159
|
/**
|
|
119
160
|
* Add evidence from an operator.
|
|
120
161
|
*
|
|
162
|
+
* NB: the operatorKit is responsible for
|
|
163
|
+
*
|
|
121
164
|
* @param {CctpTxEvidence} evidence
|
|
122
|
-
* @param {
|
|
165
|
+
* @param {RiskAssessment} riskAssessment
|
|
166
|
+
* @param {string} operatorId
|
|
123
167
|
*/
|
|
124
|
-
|
|
125
|
-
const { pending } = this.state;
|
|
126
|
-
trace(
|
|
127
|
-
'submitEvidence',
|
|
128
|
-
operatorKit.operator.getStatus().operatorId,
|
|
129
|
-
evidence,
|
|
130
|
-
);
|
|
131
|
-
const { operatorId } = operatorKit.operator.getStatus();
|
|
132
|
-
|
|
133
|
-
// TODO should this verify that the operator is one made by this exo?
|
|
134
|
-
// This doesn't work...
|
|
135
|
-
// operatorKit === operators.get(operatorId) ||
|
|
136
|
-
// Fail`operatorKit mismatch`;
|
|
168
|
+
attest(evidence, riskAssessment, operatorId) {
|
|
169
|
+
const { operators, pending, risks } = this.state;
|
|
170
|
+
trace('attest', operatorId, evidence);
|
|
137
171
|
|
|
172
|
+
// TODO https://github.com/Agoric/agoric-sdk/pull/10720
|
|
138
173
|
// TODO validate that it's a valid for Fast USDC before accepting
|
|
139
174
|
// E.g. that the `recipientAddress` is the FU settlement account and that
|
|
140
175
|
// the EUD is a chain supported by FU.
|
|
@@ -147,6 +182,9 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
|
|
|
147
182
|
trace(`operator ${operatorId} already reported ${txHash}`);
|
|
148
183
|
} else {
|
|
149
184
|
pendingStore.init(txHash, evidence);
|
|
185
|
+
// accept the risk assessment as well
|
|
186
|
+
const riskStore = risks.get(operatorId);
|
|
187
|
+
riskStore.init(txHash, riskAssessment);
|
|
150
188
|
}
|
|
151
189
|
}
|
|
152
190
|
|
|
@@ -154,25 +192,66 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
|
|
|
154
192
|
const found = [...pending.values()].filter(store =>
|
|
155
193
|
store.has(txHash),
|
|
156
194
|
);
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
195
|
+
const minAttestations = Math.ceil(operators.getSize() / 2);
|
|
196
|
+
trace(
|
|
197
|
+
'transaction',
|
|
198
|
+
txHash,
|
|
199
|
+
'has',
|
|
200
|
+
found.length,
|
|
201
|
+
'of',
|
|
202
|
+
minAttestations,
|
|
203
|
+
'necessary attestations',
|
|
204
|
+
);
|
|
205
|
+
if (found.length < minAttestations) {
|
|
160
206
|
return;
|
|
161
207
|
}
|
|
162
208
|
|
|
163
|
-
|
|
209
|
+
let lastEvidence;
|
|
210
|
+
for (const store of found) {
|
|
211
|
+
const next = store.get(txHash);
|
|
212
|
+
if (lastEvidence) {
|
|
213
|
+
if (keyEQ(lastEvidence, next)) {
|
|
214
|
+
lastEvidence = next;
|
|
215
|
+
} else {
|
|
216
|
+
trace(
|
|
217
|
+
'🚨 conflicting evidence for',
|
|
218
|
+
txHash,
|
|
219
|
+
':',
|
|
220
|
+
lastEvidence,
|
|
221
|
+
'!=',
|
|
222
|
+
next,
|
|
223
|
+
);
|
|
224
|
+
Fail`conflicting evidence for ${quote(txHash)}`;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
lastEvidence = next;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const riskStores = [...risks.values()].filter(store =>
|
|
231
|
+
store.has(txHash),
|
|
232
|
+
);
|
|
233
|
+
// take the union of risks identified from all operators
|
|
234
|
+
const risksIdentified = allRisksIdentified(riskStores, txHash);
|
|
164
235
|
|
|
165
|
-
//
|
|
166
|
-
for (const
|
|
167
|
-
|
|
236
|
+
// sufficient agreement, so remove from pending risks, then publish
|
|
237
|
+
for (const store of found) {
|
|
238
|
+
store.delete(txHash);
|
|
239
|
+
}
|
|
240
|
+
for (const store of riskStores) {
|
|
241
|
+
store.delete(txHash);
|
|
168
242
|
}
|
|
169
|
-
|
|
243
|
+
trace('publishing evidence', evidence, risksIdentified);
|
|
244
|
+
publisher.publish({
|
|
245
|
+
evidence,
|
|
246
|
+
risk: { risksIdentified },
|
|
247
|
+
});
|
|
170
248
|
},
|
|
171
249
|
},
|
|
172
250
|
public: {
|
|
173
251
|
getEvidenceSubscriber: () => subscriber,
|
|
174
252
|
},
|
|
175
253
|
},
|
|
254
|
+
{ stateShape },
|
|
176
255
|
);
|
|
177
256
|
};
|
|
178
257
|
harden(prepareTransactionFeedKit);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/** @file core-eval to publish update to Fast USDC feedPolicy */
|
|
2
|
+
|
|
3
|
+
import { E } from '@endo/far';
|
|
4
|
+
import { fromExternalConfig } from './utils/config-marshal.js';
|
|
5
|
+
import { FeedPolicyShape } from './type-guards.js';
|
|
6
|
+
import { publishFeedPolicy } from './utils/core-eval.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @import {Issuer} from '@agoric/ertp';
|
|
10
|
+
* @import {Passable} from '@endo/pass-style'
|
|
11
|
+
* @import {BootstrapManifest} from '@agoric/vats/src/core/lib-boot.js'
|
|
12
|
+
* @import {LegibleCapData} from './utils/config-marshal.js'
|
|
13
|
+
* @import {FeedPolicy} from './types.js'
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const contractName = 'fastUsdc';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {BootstrapPowers &
|
|
20
|
+
* { consume: { chainStorage: Promise<StorageNode> }}
|
|
21
|
+
* } powers
|
|
22
|
+
* @param {{ options: LegibleCapData<{feedPolicy: FeedPolicy & Passable}> }} config
|
|
23
|
+
*/
|
|
24
|
+
export const updateFastUsdcPolicy = async (
|
|
25
|
+
{ consume: { agoricNames, chainStorage } },
|
|
26
|
+
config,
|
|
27
|
+
) => {
|
|
28
|
+
/** @type {Issuer<'nat'>} */
|
|
29
|
+
const USDCissuer = await E(agoricNames).lookup('issuer', 'USDC');
|
|
30
|
+
const brands = harden({
|
|
31
|
+
USDC: await E(USDCissuer).getBrand(),
|
|
32
|
+
});
|
|
33
|
+
const { feedPolicy } = fromExternalConfig(
|
|
34
|
+
config.options,
|
|
35
|
+
brands,
|
|
36
|
+
harden({ feedPolicy: FeedPolicyShape }),
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const storageNode = await E(chainStorage).makeChildNode(contractName);
|
|
40
|
+
|
|
41
|
+
await publishFeedPolicy(storageNode, feedPolicy);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {unknown} _utils
|
|
46
|
+
* @param {{
|
|
47
|
+
* options: LegibleCapData<{feedPolicy: FeedPolicy & Passable}>;
|
|
48
|
+
* }} param1
|
|
49
|
+
*/
|
|
50
|
+
export const getManifestForUpdateFastUsdcPolicy = (_utils, { options }) => {
|
|
51
|
+
return {
|
|
52
|
+
/** @type {BootstrapManifest} */
|
|
53
|
+
manifest: {
|
|
54
|
+
[updateFastUsdcPolicy.name]: {
|
|
55
|
+
consume: {
|
|
56
|
+
chainStorage: true,
|
|
57
|
+
|
|
58
|
+
// widely shared: name services
|
|
59
|
+
agoricNames: true,
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
options,
|
|
64
|
+
};
|
|
65
|
+
};
|