forked from Agoric/agoric-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(liquidationVisibility): Add a3p proposal
Refs: #35
- Loading branch information
1 parent
57acbf9
commit 1185474
Showing
46 changed files
with
6,999 additions
and
0 deletions.
There are no files selected for viewing
2 changes: 2 additions & 0 deletions
2
a3p-integration/proposals/d:liquidation-visibility/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.yarn | ||
artifacts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
nodeLinker: node-modules |
88 changes: 88 additions & 0 deletions
88
a3p-integration/proposals/d:liquidation-visibility/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# Liquidation Visibility | ||
This proposal aims to perform a `core-eval` upgrade to `vaultFactory`. The purpose of the upgrade is to | ||
improve the visibility of liquidating vaults. For the full spec please see [this issue](https://github.com/Jorge-Lopes/liquidation-visibility/issues/2) | ||
and for minor additional specs see [this one](https://github.com/Jorge-Lopes/agoric-sdk/issues/36). | ||
|
||
## Work Backlog | ||
* Main workspace => https://github.com/Jorge-Lopes/agoric-sdk | ||
* PR => https://github.com/Agoric/agoric-sdk/pull/8994 | ||
* Release => https://github.com/Jorge-Lopes/agoric-sdk/releases/tag/liq-visibility-a3p-v0.2 | ||
|
||
## Test Structure | ||
We follow the usual `a3p` flow where we first perform our upgrade at `EVAL` phase then run our tests in `TEST` | ||
phase. Notice that we don't run anything under `USE` phase as we don't want the changes we make to create the | ||
appropriate test circumstances to effect future builds. | ||
|
||
To execute our core-eval we use; | ||
* [test-liquidation-visibility.js](./test-liquidation-visibility.js) | ||
|
||
Our main challenge in testing the visibility of liquidations is to trigger an actual liquidation in our post | ||
eval tests. Below files are used to set up that environment; | ||
* [post.liquidation.js](./post.liquidation.js) | ||
* [post.test.js](./post.test.js) | ||
|
||
And test our desired behavior we use; | ||
* [post.scenario.js](./post.scenario.js) | ||
|
||
## How to trigger liquidation? | ||
In the below diagram, we describe the steps we go thorough to trigger a fake liquidation. | ||
The reason why it is problematic subject is; | ||
1. We need to be able to control the time and `chainTimerService` does not allow that | ||
2. Auctioneer at this version is not upgradable so we have to deploy a new one | ||
3. We have to make sure `vaultFactory` does use our fake auctioneer and the timer we want | ||
* The problem with this one is with making sure while we adjust the code base to serve | ||
our needs to create a suitable liquidation environment, we also have to make sure our tests | ||
are actually reliable(we test what we will be deploying to the mainnet). | ||
|
||
|
||
### Addressing problem #3 | ||
In order to get around this problem we've created a tarball file ([visibilityFeaturesProof.tar](./visibilityFeaturesProof.tar)) | ||
that has what we've developed and put the same file in both the [relase](https://github.com/Jorge-Lopes/agoric-sdk/releases/tag/liq-visibility-a3p-v0.2). | ||
Basically what we do with that file is; | ||
* Check the local and remote versions match using `cksum` | ||
* Move the incarnation 1 code to `/usr/src/agoric-sdk` | ||
* Bundle `inter-protocol` again | ||
* Make sure the vaultFactory bundle hash matches the one we use to perform our core-eval | ||
* At this stage we're sure that the version we have in `/usr/src/agoric-sdk` is the same | ||
as the one we deployed | ||
* Adjust VF code programmatically in [post.liquidation.js](./post.liquidation.js) to | ||
make sure it uses the fake auctioneer and manual timer so that we can trigger the liquidation | ||
|
||
### The whole proposal flow | ||
|
||
```mermaid | ||
sequenceDiagram | ||
participant image as ghcr.io/agoric/agoric-3-proposals | ||
participant web as release | ||
Note over image,image: vaultFactory: inc 0 code | ||
Note over testFlow,agd: PHASE: EVAL | ||
testFlow ->>+ agd: test-liquidation-visibility.js | ||
agd -->>- testFlow: upgrade successful | ||
Note over agd,agd: vaultFactory: inc 1 | ||
Note over testFlow,agd: PHASE: TEST | ||
Note over testFlow,testFlow: post.liquidation.js running | ||
testFlow ->>+ web: fetch vaultFactory inc 1 code | ||
web -->>- testFlow: incarnation 1 code | ||
testFlow ->> testFlow: make sure inc 1 code matches the local one | ||
testFlow ->> testFlow: unarchive local inc 1 code | ||
testFlow ->> image: copy vaultFactory inc 1 code | ||
Note over image,image: vaultFactory: inc 1 code | ||
testFlow ->> image: bundle vaultFactory | ||
testFlow ->> testFlow: check bundle hash from the image matches inc 1's bundle hash | ||
Note over testFlow, testFlow: we must use a manual timer to trigger liquidation | ||
testFlow ->> testFlow: update vaultFactory.js, vaultDirector.js, vaultManager.js | ||
Note over testFlow, testFlow: we must deploy a new auctioneer as well that uses the same timer as VF | ||
testFlow ->> testFlow: build proposal to deploy changes required to trigger liquidation | ||
testFlow ->> agd: Execute built proposal | ||
Note over agd,agd: vaultFactory: inc 2 | ||
Note over testFlow,testFlow: post.test.js running | ||
testFlow ->> agd: deploy a new vaultManager for the asset STARS | ||
Note over testFlow, agd: we use addSTARS.js from. the sdk | ||
testFlow ->> testFlow: accept oracle invitations | ||
testFlow ->> testFlow: push STARS/IST price | ||
Note over testFlow,testFlow: post.scenario.js running | ||
testFlow ->> testFlow: open STARS vaults | ||
testFlow ->> testFlow: place bids to fake auctioneer | ||
testFlow ->> testFlow: make sure aution is run and bids are settled | ||
testFlow ->> testFlow: assert the visibility of the liquidation | ||
``` |
5 changes: 5 additions & 0 deletions
5
...a6fe07784697fa8b40bcbc8f3ab1fd92a6d7ce8197efa0d2a28716737f77c68ab2eba88b3c72179f15e0.json
Large diffs are not rendered by default.
Oops, something went wrong.
5 changes: 5 additions & 0 deletions
5
...5160ee0042cf0cb4136bdba57165a7ca70b78b37402404aaafc02400019383c6d6b076a7236a352a6ba3.json
Large diffs are not rendered by default.
Oops, something went wrong.
17 changes: 17 additions & 0 deletions
17
...ation/proposals/d:liquidation-visibility/assets/upgrade-vaults-liq-visibility-permit.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"consume": { | ||
"vaultFactoryKit": "to upgrade vaultFactory using its adminFacet", | ||
"agoricNamesAdmin": "makeCoreProposalBehavior", | ||
"vatAdminSvc": "makeCoreProposalBehavior", | ||
"zoe": "makeCoreProposalBehavior" | ||
}, | ||
"evaluateBundleCap": "makeCoreProposalBehavior", | ||
"installation": { | ||
"produce": "makeCoreProposalBehavior" | ||
}, | ||
"modules": { | ||
"utils": { | ||
"runModuleBehaviors": "makeCoreProposalBehavior" | ||
} | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
...gration/proposals/d:liquidation-visibility/assets/upgrade-vaults-liq-visibility-plan.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"name": "upgrade-vaults-liq-visibility", | ||
"script": "upgrade-vaults-liq-visibility.js", | ||
"permit": "upgrade-vaults-liq-visibility-permit.json", | ||
"bundles": [ | ||
{ | ||
"entrypoint": "../src/vaultFactory/vaultFactory.js", | ||
"bundleID": "b1-0daeb28abf2bb95cd27bebe80cdcd53ecd670244cb4ca6fe07784697fa8b40bcbc8f3ab1fd92a6d7ce8197efa0d2a28716737f77c68ab2eba88b3c72179f15e0", | ||
"fileName": "/Users/anil/.agoric/cache/b1-0daeb28abf2bb95cd27bebe80cdcd53ecd670244cb4ca6fe07784697fa8b40bcbc8f3ab1fd92a6d7ce8197efa0d2a28716737f77c68ab2eba88b3c72179f15e0.json" | ||
}, | ||
{ | ||
"entrypoint": "../src/proposals/vaultsUpgrade.js", | ||
"bundleID": "b1-88b8532be656b66ebc0298f916802fae523a263bd1935160ee0042cf0cb4136bdba57165a7ca70b78b37402404aaafc02400019383c6d6b076a7236a352a6ba3", | ||
"fileName": "/Users/anil/.agoric/cache/b1-88b8532be656b66ebc0298f916802fae523a263bd1935160ee0042cf0cb4136bdba57165a7ca70b78b37402404aaafc02400019383c6d6b076a7236a352a6ba3.json" | ||
} | ||
] | ||
} |
155 changes: 155 additions & 0 deletions
155
a3p-integration/proposals/d:liquidation-visibility/assets/upgrade-vaults-liq-visibility.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
// This is generated by writeCoreProposal; please edit! | ||
/* eslint-disable */ | ||
|
||
const manifestBundleRef = {bundleID:"b1-88b8532be656b66ebc0298f916802fae523a263bd1935160ee0042cf0cb4136bdba57165a7ca70b78b37402404aaafc02400019383c6d6b076a7236a352a6ba3"}; | ||
const getManifestCall = harden([ | ||
"getManifestVaultsUpgrade", | ||
{ | ||
vaultFactoryRef: { | ||
bundleID: "b1-0daeb28abf2bb95cd27bebe80cdcd53ecd670244cb4ca6fe07784697fa8b40bcbc8f3ab1fd92a6d7ce8197efa0d2a28716737f77c68ab2eba88b3c72179f15e0", | ||
}, | ||
}, | ||
]); | ||
const customManifest = { | ||
upgradeVaults: { | ||
consume: { | ||
vaultFactoryKit: "to upgrade vaultFactory using its adminFacet", | ||
}, | ||
}, | ||
}; | ||
|
||
// Make a behavior function and "export" it by way of script completion value. | ||
// It is constructed by an anonymous invocation to ensure the absence of a global binding | ||
// for makeCoreProposalBehavior, which may not be necessary but preserves behavior pre-dating | ||
// https://github.com/Agoric/agoric-sdk/pull/8712 . | ||
const behavior = (({ | ||
manifestBundleRef, | ||
getManifestCall: [manifestGetterName, ...manifestGetterArgs], | ||
customManifest, | ||
E, | ||
log = console.info, | ||
customRestoreRef, | ||
}) => { | ||
const { entries, fromEntries } = Object; | ||
|
||
// deeplyFulfilled is a bit overkill for what we need. | ||
const shallowlyFulfilled = async obj => { | ||
if (!obj) { | ||
return obj; | ||
} | ||
const ents = await Promise.all( | ||
entries(obj).map(async ([key, valueP]) => { | ||
const value = await valueP; | ||
return [key, value]; | ||
}), | ||
); | ||
return fromEntries(ents); | ||
}; | ||
|
||
const makeRestoreRef = (vatAdminSvc, zoe) => { | ||
/** @type {(ref: import\('./externalTypes.js').ManifestBundleRef) => Promise<Installation<unknown>>} */ | ||
const defaultRestoreRef = async bundleRef => { | ||
// extract-proposal.js creates these records, and bundleName is | ||
// the optional name under which the bundle was installed into | ||
// config.bundles | ||
const bundleIdP = | ||
'bundleName' in bundleRef | ||
? E(vatAdminSvc).getBundleIDByName(bundleRef.bundleName) | ||
: bundleRef.bundleID; | ||
const bundleID = await bundleIdP; | ||
const label = bundleID.slice(0, 8); | ||
return E(zoe).installBundleID(bundleID, label); | ||
}; | ||
return defaultRestoreRef; | ||
}; | ||
|
||
/** @param {ChainBootstrapSpace & BootstrapPowers & { evaluateBundleCap: any }} powers */ | ||
const coreProposalBehavior = async powers => { | ||
// NOTE: `powers` is expected to match or be a superset of the above `permits` export, | ||
// which should therefore be kept in sync with this deconstruction code. | ||
// HOWEVER, do note that this function is invoked with at least the *union* of powers | ||
// required by individual moduleBehaviors declared by the manifest getter, which is | ||
// necessary so it can use `runModuleBehaviors` to provide the appropriate subset to | ||
// each one (see ./writeCoreProposal.js). | ||
// Handle `powers` with the requisite care. | ||
const { | ||
consume: { vatAdminSvc, zoe, agoricNamesAdmin }, | ||
evaluateBundleCap, | ||
installation: { produce: produceInstallations }, | ||
modules: { | ||
utils: { runModuleBehaviors }, | ||
}, | ||
} = powers; | ||
|
||
// Get the on-chain installation containing the manifest and behaviors. | ||
log('evaluateBundleCap', { | ||
manifestBundleRef, | ||
manifestGetterName, | ||
vatAdminSvc, | ||
}); | ||
let bcapP; | ||
if ('bundleName' in manifestBundleRef) { | ||
bcapP = E(vatAdminSvc).getNamedBundleCap(manifestBundleRef.bundleName); | ||
} else if ('bundleID' in manifestBundleRef) { | ||
bcapP = E(vatAdminSvc).getBundleCap(manifestBundleRef.bundleID); | ||
} else { | ||
const keys = Reflect.ownKeys(manifestBundleRef).map(key => | ||
typeof key === 'string' ? JSON.stringify(key) : String(key), | ||
); | ||
const keysStr = `[${keys.join(', ')}]`; | ||
throw Error( | ||
`bundleRef must have own bundleName or bundleID, missing in ${keysStr}`, | ||
); | ||
} | ||
const bundleCap = await bcapP; | ||
|
||
const proposalNS = await evaluateBundleCap(bundleCap); | ||
|
||
// Get the manifest and its metadata. | ||
log('execute', { | ||
manifestGetterName, | ||
bundleExports: Object.keys(proposalNS), | ||
}); | ||
const restoreRef = customRestoreRef || makeRestoreRef(vatAdminSvc, zoe); | ||
const { | ||
manifest, | ||
options: rawOptions, | ||
installations: rawInstallations, | ||
} = await proposalNS[manifestGetterName]( | ||
harden({ restoreRef }), | ||
...manifestGetterArgs, | ||
); | ||
|
||
// Await references in the options or installations. | ||
const [options, installations] = await Promise.all( | ||
[rawOptions, rawInstallations].map(shallowlyFulfilled), | ||
); | ||
|
||
// Publish the installations for our dependencies. | ||
const installationEntries = entries(installations || {}); | ||
if (installationEntries.length > 0) { | ||
const installAdmin = E(agoricNamesAdmin).lookupAdmin('installation'); | ||
await Promise.all( | ||
installationEntries.map(([key, value]) => { | ||
produceInstallations[key].resolve(value); | ||
return E(installAdmin).update(key, value); | ||
}), | ||
); | ||
} | ||
|
||
// Evaluate the manifest. | ||
return runModuleBehaviors({ | ||
// Remember that `powers` may be arbitrarily broad. | ||
allPowers: powers, | ||
behaviors: proposalNS, | ||
manifest: customManifest || manifest, | ||
makeConfig: (name, _permit) => { | ||
log('coreProposal:', name); | ||
return { options }; | ||
}, | ||
}); | ||
}; | ||
|
||
return coreProposalBehavior; | ||
})({ manifestBundleRef, getManifestCall, customManifest, E }); | ||
behavior; |
Oops, something went wrong.