This document contains all the latest decisions about how the Multi Vault Manager Per One Collateral Type work. For history see #4.
According to the questions and their answers here, we will carry out our development.
Product Questions Asked and Answered
Questions
Is it possible to have more than one retail vault manager?
In other words, for a given and already accepted collateral type, is it safe to assume that all incoming new vault managers will be of type institutional or can EC choose to create a new retail vault manager?
Can EC add new accounts to the whitelist for a particular vault manager?
Adding new accounts to an existing institutional vault manager can be done. However, it will (probably) go through EC so it will result having its own user flow. Do we want this?
Can EC remove accounts from the whitelist for a particular vault manager?
I am not sure how this can be done but I think this would make sense when we think about the possibility business relationships coming to an end with certain institutions. Should we work on solving this problem?
Using a core-eval is the usual way for sending invitations, for example EC member invitations, by requesting either namesByAddresses or namesByAddressesAdmin to get the depositFacet for a certain account then invoking depositFacet.receive(invitation). This process, of course, includes a BLDer DAO voting as to the nature of core-evals.
For our case, we want EC to handle all the action which means no BLDer DAO interaction. So we need a service that can be invoked from vaultFactory. Implementing the logic in the paragraph above just for one governed api in vaultFactory seemed a little bit too ad-hoc given the generic usage such a service might have. As we are aware of @dckc's existing work called postalService, our plan is to refine that contract and deploy it on Agoric Blockchain to use for our case.
Development Questions Answered During Analysis
How is EC going to update parameters for retail and institutional VMs?
The process represented in the diagram below is expected to be the same for both retail and institutional managers as institutional manager will also have their own identifier in vstorage.
sequenceDiagram
actor mem as Member
participant ec as EC UI
participant vs as vStorage
participant sw as Member SmartWallet
participant ch as EconCharter
participant gv as VF Governor
participant vf as VaultFactory
mem ->> ec: Raise DebtLimit for ATOM-A
ec ->> vs: Query vaultManager specifiers
vs -->> ec: { collateralBrand, managerIdentifier }
ec ->> ec: Build offerSpec
ec ->> sw: Initiate election
Note over ec, sw: offerSpec = {..., offerArgs = {..., path = {paramPath = {key = {collateralBrand, managerIdentifier}}}}}
sw ->> ch: Forward offer
ch ->> ch: Lookup relevant governor
ch ->> gv: voteOnParamChanges(..., {...path})
gv ->> vf: Lookup path
vf -->> gv: ATOM-A paramManager
gv ->> gv: Election result = Positive
gv ->> gv: Update params
gv -->> sw: Offer succesful
sw -->> vs: Offer succesful
vf ->> vs: Params updated
ec ->> vs: Lookup params
ec ->> ec: Display updated params
How is an ordinary user will find the respective VM identifiers?
The new design to identify the correct vaultManager introduces a new child node under manager{manager-index} called metadata.
This metadata child can have a data model similar to below;
Note that data shown below is just a thought and not the final data model
const metadata = {
identifier,
title: "ATOM-A",
whitelist: ["agoric1....4w", "agoric1....2q", ...], // Means this is an institutional VM
}
So vstorage after the upgrade will look like below;
The process represented in the diagram below represents the logic that should be enforced when a new VaultManager is created and how it should handle both Retail and Institutional VMs
flowchart LR
A(EC) --> |Add new VM| D(VaultDirector)
D(VaultDirector) --> C{Retail or Institutional}
C -->|Retail| F(Retail VMs Store)
--> |collateralBrand| E(Get VM store for a Col Type)
--> |VM identifier| K(Init new retail VM)
C -->|Institutional| G(Institutional VM store)
--> |collateralBrand| N(Get VM store for a Col Type)
--> |VM identifier| L(Init new retail VM)
Bellow, is a representation of the key-value pairs that will be held in the Retail and Institutional VMs Store:
Retail or Institutional VMs Store
Key (collateralBrand)
Value (VM store)
stAtom
stAtomStore
stOsmo
stOsmoStore
stAtomStore
Key (VM identifier)
Value (VM)
manager101
vaultManager
manager102
vaultManager
How is an ordinary user going to open a vault on a retail VM?
sequenceDiagram
participant sw as User SmartWallet
participant vd as VaultDirector
participant vm as VaultManager
Note over sw: user selects one of the vaultManagers displayed on dapp-inter
sw ->> vd: getCollateralManager(brandIn, managerIdentifier)
vd ->> vd: retailVMsStore.get(brandIn)
vd ->> vd: ${brandIn}Store.get(managerIndex)
vd -->> sw : vaultManagerPublicFacet
sw ->> vm : makeVaultInvitation()
vm -->> sw : invitation
sw ->> vm : makeVaultKit()
vm -->> sw : vaultKit
How is an institutional user going to be granted access to an institutional VM?
sequenceDiagram
participant vd as VaultDirector
participant vf as VaultFactory
participant hl as VM Holder
participant sw as User SmartWallet
vd ->> vd: addNewManager(collateralBrand, initialParamValues)
vd ->> vf: makeVaultManagerKit()
vf -->> vd: kit
vd ->> hl: makeVmHolder(kit.self.getPublicFacet(), getIterationCount)
hl ->> hl: currentIteration = getIterationCount()
Note over hl: currentIteration enables revoking access
hl -->> vd: holder
Note over vd, hl: holder = {invitationMakers = {MakeVault = pf.makeVaultInvitation}, holder = { getQuotes, getCompoundedInterest, getPublicTopics }}
vd ->> sw: holder
How is an institutional user going to receive the InvitationMakers required to to open a vault?
It is important to highlight that the sendBatchTo method is NOT currently implemented in the postal-service.contract, but we are considering to include it to make the API more friendly for our use case.
sequenceDiagram
actor I as Institution
participant VD as VaultDirector
participant Zoe
participant PS as PostalService
Note over VD: VaultDirector is provisioned with PostalService Instance
VD ->> Zoe: getPublicFacet(PostalServiceInstance)
Zoe -->> VD: PostalServicePF
VD ->> PS: sendBatchTo(address, invitationMakers = { makeVaultInvitation })
loop VaultManager whitelisted addresses
PS ->> I: invitationMakers
end
How is an institutional user going to open a vault on an institutional VM?
sequenceDiagram
actor us as Institutional User
participant ui as dapp-inter
participant sw as User SmartWallet
participant ivm as Institutional VM
us ->> ui: select institutional VM
us ->> ui: enter vault parameters
us ->> ui: click open vault
ui ->> ui: build offer spec
note over ui: {invitationSpec= {previousOffer= "{$address-manager-$managerIndex}"}, proposal, offerArgs}
ui ->> sw: offer sent
sw ->> sw: find continuing invitation for {$address-manager-$managerIndex}
sw ->> sw: invitationMakers.makeVaultInvitation()
sw ->> ivm: forward offer
ivm ->> ivm: makeVatultKit()
ivm -->> sw: vaultHolder
sw -->> ui: success
How is the UX like for an institutional user accept their invitation?
sequenceDiagram
actor ins as Institutional User
participant ec as EC UI
participant sw as User SmartWallet
participant ecc as EC Charter
Note over ins, sw: New vm added and invitations already sent
ec -->> ins: [Off Chain] check your invitation purse and accept it
ins ->> ec: Click "Accept Institutional Invite"
ec ->> ec: build offer spec
note over ec: offerSpec = {invitationSpec= {type = "purse", ...}, ...}
ec ->> sw: send offer
sw ->> ecc: accept institutional invite
ecc -->> sw: invitationMakers = { makeVaultInvitation }
sw -->> sw: publish offer successful
note over ins: now ready to open vaults
dapp-inter flow for opening an institutional vault
sequenceDiagram
participant user as institutionalUser
participant int as dapp-inter
participant vs as vStorage
participant vf as vaultFactory
user ->> int: connect keplr
int ->> vs: query = list of institutional managers and the white-list
vs -->> int: [manager0, manager1]
Note over int, int: find which managers the user is whitelisted
int ->> int: display retail AND institutional managers
int ->> int: display all vaults belonging to the user
int -->> user: page loaded
user ->> int: Click "open vault" for institutional manager
int ->> int: calculate prevOfferId
Note over int,int: Inst users can send offers using continuing invitations
Note over int,int: e.g {address}-manager-{managerIndex}-{?iteration}
int ->> vf: Send vault offer
Note over int, vf: offer = {invitationSpec = {source = continuing, prevOfferId, makeVaultInvitation}}
vf -->> int: success
What are the structural differences between retail and institutional VMs?
A Retail Vault Manager is a vm that its public facing methods (collateral facet) are accessible to anybody. Anyone wishing to open a vault in these VMs can do so.
An Institutional Vault Manager is a vm that only a set whitelisted account can access its public facing methods (collateral facet). EC is in charge of determining the whitelisted accounts. If manager{managerIndex} storage node's child node metadata has a non-empty whitelist array, this means that vault manager is for institutional purposes and only those accounts listed under metadata.whitelist can send transactions to interact with that VM.
Is this new way of storing VMs going to cause any changes how vault lifecycles are carried out?
As far as I can see, vault lifecycle is handled separately via methods of vaultHolder. As a result for an institutional user having vaults from both institutional and retails VMs, all those vaults show up under wallet.{address}.current.offerToPublicSubscriberPaths with their own offerId as the key value. As a result an institutional user's smart wallet will have lifecycle methods for both institutional and retail vaults. Therefor, I don't expect any changes to the process as well.
Test Plan
The functionality we want to make sure works properly here is;
When adding a new institutional manager paramManagers are handled correctly in vaultDirector [Unit, Swingset]
EC can govern new institutional managers parameters [Unit, Swingset]
Adding a new institutional manager results with white-listed accounts receive their continuing invitations [Swingset]
This step will require a separate contract like postalService which will need its own tests [Unit, Swingset]
Confirm that whitelisted accounts can open vaults on their institutional managers [Unit, Swingset]
Make sure EC can extend the whitelist for an institutional VM [Swingset, a3p]
Confirm that the lifecycle of whitelisted accounts’ vaults can be carried out just like retail vaults [Unit, Swingset]
Confirm that institutional vaults can be liquidated [Unit, Swingset]
Confirm that one retail manager and one institutional manager for a collateral type can be liquidated together and their proceeds are distributed correctly [Unit, Swingset]
Make sure all the functionality above can be accomplished after an upgrade [Swingset, a3p]
Make sure all the functionality above are accomplished as a result of an EC election [Swingset, a3p]
Ensure that functionality that is not related to whitelisted accounts also work for retail vault managers [Unit, Swingset, a3p]
Clients can easily send offers to the retail vm of their choosing [Swingset, a3p]
Context
This document contains all the latest decisions about how the
Multi Vault Manager Per One Collateral Type
work. For history see #4.According to the questions and their answers here, we will carry out our development.
Product Questions Asked and Answered
Questions
Agoric OpCo Answers
@otoole-brendan answered;
For reference, see https://github.com/anilhelvaci/agoric-sdk/issues/4#issuecomment-2223755482
Case for
PostalService
Using a
core-eval
is the usual way for sending invitations, for example EC member invitations, by requesting eithernamesByAddresses
ornamesByAddressesAdmin
to get thedepositFacet
for a certain account then invokingdepositFacet.receive(invitation)
. This process, of course, includes a BLDer DAO voting as to the nature ofcore-eval
s.For our case, we want EC to handle all the action which means no BLDer DAO interaction. So we need a service that can be invoked from
vaultFactory
. Implementing the logic in the paragraph above just for one governed api invaultFactory
seemed a little bit too ad-hoc given the generic usage such a service might have. As we are aware of @dckc's existing work called postalService, our plan is to refine that contract and deploy it on Agoric Blockchain to use for our case.Development Questions Answered During Analysis
How is EC going to update parameters for
retail
andinstitutional
VMs?The process represented in the diagram below is expected to be the same for both
retail
andinstitutional
managers as institutional manager will also have their own identifier invstorage
.How is an ordinary user will find the respective VM identifiers?
The new design to identify the correct vaultManager introduces a new child node under
manager{manager-index}
calledmetadata
.This metadata child can have a data model similar to below;
So
vstorage
after the upgrade will look like below;Form of VM Identifiers: String vs Handle? [WIP]
VM identifiers are intended to serve as the key in
vmStore
. Here are main parameters I use to decide;See discussion in
agoric-sdk
=> [Agoric#9663](https://github.com/Agoric/agoric-sdk/discussions/9663)How will vaultManagers be stored and organised?
The process represented in the diagram below represents the logic that should be enforced when a new VaultManager is created and how it should handle both Retail and Institutional VMs
Bellow, is a representation of the key-value pairs that will be held in the Retail and Institutional VMs Store:
How is an ordinary user going to open a vault on a retail VM?
How is an institutional user going to be granted access to an institutional VM?
How is an institutional user going to receive the InvitationMakers required to to open a vault?
It is important to highlight that the
sendBatchTo
method is NOT currently implemented in the postal-service.contract, but we are considering to include it to make the API more friendly for our use case.How is an institutional user going to open a vault on an institutional VM?
How is the UX like for an institutional user accept their invitation?
For ref => https://github.com/anilhelvaci/agoric-sdk/issues/3#issuecomment-2226855685
dapp-inter
flow for opening an institutional vaultWhat are the structural differences between retail and institutional VMs?
A
Retail Vault Manager
is a vm that its public facing methods (collateral
facet) are accessible to anybody. Anyone wishing to open a vault in these VMs can do so.An
Institutional Vault Manager
is a vm that only a set whitelisted account can access its public facing methods (collateral
facet). EC is in charge of determining the whitelisted accounts. Ifmanager{managerIndex}
storage node's child nodemetadata
has a non-emptywhitelist
array, this means that vault manager is for institutional purposes and only those accounts listed undermetadata.whitelist
can send transactions to interact with that VM.Is this new way of storing VMs going to cause any changes how vault lifecycles are carried out?
As far as I can see, vault lifecycle is handled separately via methods of
vaultHolder
. As a result for an institutional user having vaults from both institutional and retails VMs, all those vaults show up underwallet.{address}.current.offerToPublicSubscriberPaths
with their ownofferId
as the key value. As a result an institutional user's smart wallet will have lifecycle methods for both institutional and retail vaults. Therefor, I don't expect any changes to the process as well.Test Plan
The functionality we want to make sure works properly here is;