-
Notifications
You must be signed in to change notification settings - Fork 212
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
make Chainlink the canonical priceAggregator #6629
Changes from all commits
a960dda
ed950f5
e1f7488
a03a92d
d63ddb2
28d1564
274a10b
a28c8f7
2a2e559
9f6fd6b
642cb37
9e2617b
4899d40
efe9d11
8f7601c
e3e3984
30d3966
d7ad277
5e58585
9914899
bb2b503
443ea1c
a8c836c
61662e7
21018a1
8e61373
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -87,7 +87,7 @@ export const ensureOracleBrands = async ( | |||
|
||||
/** | ||||
* @param {ChainBootstrapSpace} powers | ||||
* @param {{options: {priceFeedOptions: {AGORIC_INSTANCE_NAME: string, oracleAddresses: string[], contractTerms: unknown, IN_BRAND_NAME: string, OUT_BRAND_NAME: string}}}} config | ||||
* @param {{options: {priceFeedOptions: {AGORIC_INSTANCE_NAME: string, oracleAddresses: string[], contractTerms: import('@agoric/zoe/src/contracts/priceAggregatorChainlink.js').ChainlinkConfig, IN_BRAND_NAME: string, OUT_BRAND_NAME: string}}}} config | ||||
*/ | ||||
export const createPriceFeed = async ( | ||||
{ | ||||
|
@@ -129,7 +129,7 @@ export const createPriceFeed = async ( | |||
/** | ||||
* Values come from economy-template.json, which at this writing had IN:ATOM, OUT:USD | ||||
* | ||||
* @type {[[Brand<'nat'>, Brand<'nat'>], [Installation<import('@agoric/zoe/src/contracts/priceAggregator.js').start>]]} | ||||
* @type {[[Brand<'nat'>, Brand<'nat'>], [Installation<import('@agoric/zoe/src/contracts/priceAggregatorChainlink.js').start>]]} | ||||
*/ | ||||
const [[brandIn, brandOut], [priceAggregator]] = await Promise.all([ | ||||
reserveThenGetNames(E(agoricNamesAdmin).lookupAdmin('oracleBrand'), [ | ||||
|
@@ -142,7 +142,6 @@ export const createPriceFeed = async ( | |||
]); | ||||
|
||||
const unitAmountIn = await unitAmount(brandIn); | ||||
/** @type {import('@agoric/zoe/src/contracts/priceAggregator.js').PriceAggregatorContract['terms']} */ | ||||
const terms = await deeplyFulfilledObject( | ||||
harden({ | ||||
...contractTerms, | ||||
|
@@ -188,11 +187,11 @@ export const createPriceFeed = async ( | |||
.then(deleter => E(aggregators).set(terms, { aggregator, deleter })); | ||||
|
||||
/** | ||||
* Send an invitation to one of the oracles. | ||||
* Initialize a new oracle and send an invitation to administer it. | ||||
* | ||||
* @param {string} addr | ||||
*/ | ||||
const distributeInvitation = async addr => { | ||||
const addOracle = async addr => { | ||||
const invitation = await E(aggregator.creatorFacet).makeOracleInvitation( | ||||
addr, | ||||
); | ||||
|
@@ -205,7 +204,7 @@ export const createPriceFeed = async ( | |||
}; | ||||
|
||||
trace('distributing invitations', oracleAddresses); | ||||
await Promise.all(oracleAddresses.map(distributeInvitation)); | ||||
await Promise.all(oracleAddresses.map(addOracle)); | ||||
trace('createPriceFeed complete'); | ||||
}; | ||||
|
||||
|
@@ -306,7 +305,12 @@ export const startPriceFeeds = async ( | |||
priceFeedOptions: { | ||||
AGORIC_INSTANCE_NAME: `${inBrandName}-${outBrandName} price feed`, | ||||
contractTerms: { | ||||
POLL_INTERVAL: 1n, | ||||
minSubmissionCount: 2, | ||||
minSubmissionValue: 1, | ||||
maxSubmissionCount: 5, | ||||
maxSubmissionValue: 99999, | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's this limitation of 100k - 1? I aim to look around a bit more... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nothing purposeful. It's much bigger in
Any suggestions? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand the purpose of the limitation. What is it limiting? What bad thing might happen if there's no limit? Why is 100k a plausible number? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It's limiting the maximum value in a submission.
One is that it came in the port of https://github.com/smartcontractkit/chainlink/blob/b045416ebca769aa69bde2da23b5109abe07a8b5/contracts/src/v0.6/FluxAggregator.sol#L155-L156
If enough oracles were compromised they could push the median up to a ludicrous price. Or if there is a software bug affecting all of them it wouldn't even require malice. TMK it's a hedge against run-away values.
I don't know that it is. This code isn't of the economics or risk, just the functionality. Isn't that sufficient? |
||||
restartDelay: 1n, | ||||
timeout: 10, | ||||
}, | ||||
oracleAddresses: demoOracleAddresses, | ||||
IN_BRAND_NAME: inBrandName, | ||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,13 +10,12 @@ import { | |
import { eventLoopIteration } from '@agoric/zoe/tools/eventLoopIteration.js'; | ||
import { E } from '@endo/far'; | ||
|
||
import { INVITATION_MAKERS_DESC } from '@agoric/zoe/src/contracts/priceAggregator.js'; | ||
import buildManualTimer from '@agoric/zoe/tools/manualTimer.js'; | ||
import { AmountMath } from '@agoric/ertp'; | ||
import { coalesceUpdates } from '@agoric/smart-wallet/src/utils.js'; | ||
import { INVITATION_MAKERS_DESC } from '@agoric/zoe/src/contracts/priceAggregatorChainlink.js'; | ||
import buildManualTimer from '@agoric/zoe/tools/manualTimer.js'; | ||
import { ensureOracleBrands } from '../../src/proposals/price-feed-proposal.js'; | ||
import { makeDefaultTestContext } from './contexts.js'; | ||
import { headValue } from '../supports.js'; | ||
import { makeDefaultTestContext } from './contexts.js'; | ||
Comment on lines
-13
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there anything to this change besides line order? I can't tell. Is there some motivation for changing the order? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was some import to remove and I used Organize imports in VS Code (from TypeScript LSP) |
||
|
||
/** | ||
* @type {import('ava').TestFn<Awaited<ReturnType<makeDefaultTestContext>> | ||
|
@@ -87,18 +86,15 @@ test('admin price', async t => { | |
const currentSub = E(wallet).getCurrentSubscriber(); | ||
|
||
await t.context.simpleCreatePriceFeed([operatorAddress], 'ATOM', 'USD'); | ||
const atomBrand = await E(agoricNames).lookup('oracleBrand', 'ATOM'); | ||
const usdBrand = await E(agoricNames).lookup('oracleBrand', 'USD'); | ||
|
||
const offersFacet = wallet.getOffersFacet(); | ||
|
||
/** @type {import('@agoric/zoe/src/zoeService/utils.js').Instance<import('@agoric/zoe/src/contracts/priceAggregatorChainlink.js').start>} */ | ||
const priceAggregator = await E(agoricNames).lookup( | ||
'instance', | ||
'ATOM-USD price feed', | ||
); | ||
/** @type {import('@agoric/zoe/src/contracts/priceAggregator.js').PriceAggregatorContract['publicFacet']} */ | ||
const paPublicFacet = await E(zoe).getPublicFacet(priceAggregator); | ||
const priceAuthority = await E(paPublicFacet).getPriceAuthority(); | ||
|
||
/** | ||
* get invitation details the way a user would | ||
|
@@ -159,12 +155,15 @@ test('admin price', async t => { | |
|
||
// Push a new price result ///////////////////////// | ||
|
||
/** @type {import('@agoric/zoe/src/contracts/priceAggregatorChainlink.js').PriceRound} */ | ||
const result = { roundId: 1, unitPrice: 123n }; | ||
|
||
/** @type {import('@agoric/smart-wallet/src/invitations.js').ContinuingInvitationSpec} */ | ||
const proposeInvitationSpec = { | ||
source: 'continuing', | ||
previousOffer: 44, | ||
invitationMakerName: 'makePushPriceInvitation', | ||
invitationArgs: harden([123n]), | ||
invitationMakerName: 'PushPrice', | ||
invitationArgs: harden([result]), | ||
}; | ||
|
||
/** @type {import('@agoric/smart-wallet/src/offers').OfferSpec} */ | ||
|
@@ -185,17 +184,10 @@ test('admin price', async t => { | |
// trigger an aggregation (POLL_INTERVAL=1n in context) | ||
E(manualTimer).tickN(1); | ||
|
||
const quote = await priceAuthority.quoteGiven( | ||
AmountMath.make(atomBrand, 1_000n), | ||
usdBrand, | ||
); | ||
const latestRoundSubscriber = await E(paPublicFacet).getRoundStartNotifier(); | ||
|
||
t.deepEqual(quote.quoteAmount.value[0].amountIn, { | ||
brand: atomBrand, | ||
value: 1_000n, | ||
}); | ||
t.deepEqual(quote.quoteAmount.value[0].amountOut, { | ||
brand: usdBrand, | ||
value: 123_000n, | ||
t.deepEqual((await latestRoundSubscriber.subscribeAfter()).head.value, { | ||
roundId: 1n, | ||
startedAt: 0n, | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes me wonder whether the oracle operators aware of quoting prices in integers without decimals. I'm looking around.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The vstorage path segment is still
ATOM-USD_price_feed
. Is the number of decimals available at a nearby vstorage key?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not presently. I expect the proposal config to suffice:
agoric-sdk/packages/inter-protocol/src/proposals/price-feed-proposal.js
Lines 292 to 296 in a3962a7