-
Notifications
You must be signed in to change notification settings - Fork 0
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
Multiple vault types for a given collateral type #1
Comments
Example FE flow for iteration onesequenceDiagram
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
|
New Approach to Retail VMsAfter giving some deeper thoughts, it is clear that we need identifiers for both retails and institutional VMs. Which leads me to think that we can leverage these identifiers to store our VMs. Below is a high level illustration of how I think we can store the ever increasing 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)
However, before we come to any conclusion we must answer more questions. Preferably with diagrams. Here are some of those questions. How is EC going to update parameters for
|
owned() { | |
const { vault } = this.state; | |
if (!vault) { | |
throw Fail`Using vault holder after transfer`; | |
} | |
return vault; | |
}, |
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
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
s 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.
Just to clarify if I understood your approach, the structure of VaultManagers stores will be similar to the following? Retail or Institutional VMs Store
stAtomStore
|
How is an outside user will know about the VM identifiers? How will the vstorage look like?The current structure of vStorage is:
Lets assume that we wish to implement the minimum changes possible to keep back compatibility, but still be able to open and query a vaultManager that has the same collateral as other vaultManagers. If we record on vstorage the Retail and Institutional VMs Store, from which we can fetch the manager index, we could keep the same vstorage structure by simply add a new step on the query process. Diagram in progress ... |
How is an institutional user going to be granted access to an institutional VM?Assumptions:
sequenceDiagram
actor I as Institution
participant EC as EconCommittee
participant ECC as EconCommitteeCharter
participant VD as VaultDirector
participant PS as PostalService
I ->> EC: provide account addresses to be whitelisted
I ->> EC: provide desired collateral and initialParamValues
Note over I, EC: Should the communication above happen off-chain?
EC ->> ECC: makeCharterMemberInvitation
ECC -->> EC: invitationMakers
note over EC: invitationMakerName: 'VoteOnApiCall'
note over EC: invitationArgs: [VaultDirector, addNewManager, [collateralIssuer, initialParamValues]]
EC ->> VD : executeOffer()
create participant VM as VaultManager
VD ->> VM: makeVaultManagerKit()
VM -->> VD: VaultManagerKit
VD ->> VD: Build invitationMaker for the institution
Note over VD: { invitationMakers = { GetVmPF = kit.self.getPublicFacet } }
loop Whitelisted addresses
VD ->> PS: sendTo(addr, payment)
end
PS -->> I: Invitation
I ->> I: Exercise invitation to fetch VaultManager publicFacet
I ->> VM: makeVaultInvitation()
VM -->> I: vaultKit
VaultManager collateral: M.interface('collateral', {
makeVaultInvitation: M.call().returns(M.promise()),
getPublicTopics: M.call().returns(TopicsRecordShape),
getQuotes: M.call().returns(NotifierShape),
getCompoundedInterest: M.call().returns(RatioShape),
}), |
How is an ordinary user going to open a vault on a newly added retail VM?How is an institutional user going to open a vault on an institutional VM?The difference between this approach and the existing one is that the offer to retrieve the expected 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, managerIndex, institutional: false)
alt intitutional === false
vd ->> vd: retailVMsStore.get(brandIn)
vd ->> vd: ${brandIn}Store.get(managerIndex)
else institutional === true
vd ->> vd: institutionalVMsStore.get(brandIn)
vd ->> vd: ${brandIn}Store.get(managerIndex)
note over vd: Not sure if next step is required considering that dapp-inter will only display whitelisted VMs
vd ->> vd: validate if address is whitelisted
end
vd -->> sw : vaultManagerPublicFacet
sw ->> vm : makeVaultInvitation()
vm -->> sw : invitation
Note over sw, vm: user exercises the invitation
sw ->> vm : makeVaultKit()
vm -->> sw : vaultKit
|
What are the structural differences between retail and institutional VMs?In the collapsable section bellow, it is displayed the VaultManager structure and data currently present on Vstorage. This should be kept as is for both retail and institutional VMs since it exposes the necessary data for the Note: this assume as premisse that the institutional VMs will have the same level of transparency as the retail ones. Current structure of a VaultManagerVstorage
manager0.governance: {
"value": {
"blockHeight": "14588605",
"values": [
{
"body": {
"current": {
"DebtLimit": {
"type": "amount",
"value": {
"brand": "$0.Alleged: IST brand",
"value": "+500000000000"
}
},
"InterestRate": {
"type": "ratio",
"value": {
"denominator": {
"brand": "$0",
"value": "+10000"
},
"numerator": {
"brand": "$0",
"value": "+75"
}
}
},
"LiquidationMargin": {
"type": "ratio",
"value": {
"denominator": {
"brand": "$0",
"value": "+10000"
},
"numerator": {
"brand": "$0",
"value": "+15000"
}
}
},
"LiquidationPadding": {
"type": "ratio",
"value": {
"denominator": {
"brand": "$0",
"value": "+10000"
},
"numerator": {
"brand": "$0",
"value": "+1000"
}
}
},
"LiquidationPenalty": {
"type": "ratio",
"value": {
"denominator": {
"brand": "$0",
"value": "+10000"
},
"numerator": {
"brand": "$0",
"value": "+1000"
}
}
},
"MintFee": {
"type": "ratio",
"value": {
"denominator": {
"brand": "$0",
"value": "+10000"
},
"numerator": {
"brand": "$0",
"value": "+50"
}
}
}
}
}
}
]
}
}
manager0.metrics: {
"value": {
"blockHeight": "15731831",
"values": [
{
"body": {
"liquidatingCollateral": {
"brand": "$0.Alleged: ATOM brand",
"value": "+0"
},
"liquidatingDebt": {
"brand": "$1.Alleged: IST brand",
"value": "+0"
},
"lockedQuote": null,
"numActiveVaults": 21,
"numLiquidatingVaults": 0,
"numLiquidationsAborted": 0,
"numLiquidationsCompleted": 21,
"retainedCollateral": {
"brand": "$0",
"value": "+0"
},
"totalCollateral": {
"brand": "$0",
"value": "+2372752124"
},
"totalCollateralSold": {
"brand": "$0",
"value": "+79749677"
},
"totalDebt": {
"brand": "$1",
"value": "+2852358601"
},
"totalOverageReceived": {
"brand": "$1",
"value": "+0"
},
"totalProceedsReceived": {
"brand": "$1",
"value": "+622939841"
},
"totalShortfallReceived": {
"brand": "$1",
"value": "+25127984"
}
}
}
]
}
}
manager0.quotes: {
"value": {
"blockHeight": "15766049",
"values": [
{
"body": {
"quoteAmount": {
"brand": "$0.Alleged: quote brand",
"value": [
{
"amountIn": {
"brand": "$1.Alleged: ATOM brand",
"value": "+1000000"
},
"amountOut": {
"brand": "$2.Alleged: IST brand",
"value": "+6106876"
},
"timer": "$3.Alleged: timerService",
"timestamp": {
"absValue": "+1720433835",
"timerBrand": "$4.Alleged: timerBrand"
}
}
]
},
"quotePayment": "$5.Alleged: quote payment"
},
}
]
}
}
manager0.vaults.vault0 {
"value": {
"blockHeight": "10445656",
"values": [
{
"body": {
"debtSnapshot": {
"debt": {
"brand": "$0.Alleged: IST brand",
"value": "+0"
},
"interest": {
"denominator": {
"brand": "$0",
"value": "+100"
},
"numerator": {
"brand": "$0",
"value": "+100"
}
}
},
"locked": {
"brand": "$1.Alleged: ATOM brand",
"value": "+0"
},
"vaultState": "closed"
}
}
]
}
}
One of the main structural difference that we anticipate between As described above, one possible solution for is to add an additional child node under manager{manager-index} called metadata. const metadata = {
identifier,
title: "ATOM-A",
whitelist: ["agoric1....4w", "agoric1....2q", ...], // Means this is an institutional VM
} Other structural difference is the process required to create a new VaultManager. |
@Jorge-Lopes @anilhelvaci - Can you clarify this statement? If a collateral type has already been approved by the BLD stakers - then it's over to the EC to add additional vault types of that already supported collateral type. i.e. new vault types of already supported collateral type shouldn't need to be voted in by BLD stakers. Similarly for those institutional vaults - if the collateral type has already been added via BLD stakers - i.e. ATOM then the EC should be able to create an institutional ATOM vault from the Econ Gov UI - rather than it needing to go back to BLD stakers. Does both of these flows aligns with what you had in mind? |
Yes, the flow you described aligns with our design. We are currently preparing a new issue as Analysis Milestone: 2. The goal is to provide a clear description of the intended design, supported by necessary diagrams for comprehensive visualization. This issue will take into account your responses from Analysis Milestone: 1, as well as the recent feedback you provided. |
Context
See Agoric#6518
Development Analysis
Components Expected to be Affected
We must implement a new method named
addNewManager
. This method;initialParamValues
are checked just like inaddVaultType
paramManager
sCurrently
paramManager
s are tracked for every collateral manager according to their collateral brand. Having multiple collateral managers for one collateral type will break this implementation. We must come up with a new way to track collateral managers. I suggest looking into durable handlers.Testing Considerations
Open 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 newretail
vault manager?I believe the answer to this question is most likely "yes". See #3
Can EC add new accounts to the whitelist for a particular vault manager?
Can EC remove accounts from the whitelist for a particular vault manager?
Regression Considerations
Changing the way we index vault managers would probably end up changing a lot of the existing tooling around vaultFactory.
Deliverables
All the iterations will come with their corresponding FE implementations.
Iteration One: Enable only institutional vault managers first
Iteration Two: Enable retails vault managers
The text was updated successfully, but these errors were encountered: