Skip to content
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

MVP fund accounts ("vaults") #2377

Open
barnabee opened this issue Oct 8, 2024 · 18 comments
Open

MVP fund accounts ("vaults") #2377

barnabee opened this issue Oct 8, 2024 · 18 comments

Comments

@barnabee
Copy link
Member

barnabee commented Oct 8, 2024

Vaults/fund accounts

Overview

This ticket describes the key points of an MVP fund account (hereafter: "vault") implementation in the protocol.

The functionality enabled by this would be the ability to create trading vaults in which many users can fund another user's trading.

The funds sent to a vault will be segregated and can only be used to enter and exit positions, not transferred or withdrawn. Users can redeem their share of the vault, based on their share of its value when they sent funds. Redemptions may be subject to delays and per-period maximums to allow the vault owner notice to exit positions. Vault owners will be able to specify management and performance fees, and optionally require funding keys to be whiutelisted.

Theory of operation

  • Vaults will be represented by a "virtual" public key similar to vAMM pools.
  • Creating a vault initialises one of these keys (presumably based on the hash of the transaction that created it, or similar).
  • A vault is always created for a single settlement asset (the "vault asset")
  • A vault can only trade with or hold the vault asset
  • Any other assets received as rewards, in spot trades, via trasnfers, etc. will be transferred immediately to the funders of the vault pro-rata based on their share of the vault
  • Any user can create a vault and become the owner by sending an appropriate transaction
  • Vaults have metadata: name, description, URL, image
  • Vaults have a fee period, management fee factor, and performance fee factor
    • Every time fee_period passes fees are assessed
    • The management fee is always paid each fee period
    • The performance fee is only paid on new gains [see "new gains" below] each fee period
    • Either or both fee factor(s) can be zero
    • When fees are paid, this is done by increasing the share of the vault's total assets attributed to the vault owner and decreasing the shares held by everyone else pro rata, meaning funds do not need to be available or moved between accounts to pay fees
      - Vaults have a redemption delay (which may be zero) and a maximum frfaction that can be redeemed per some period (daily?) see below comments for updated redemption logic
  • The owner can update, close, or change the owning key of a vault
  • A vault can only be closed when it has no open position and all funds are in the general account
  • Vault owner can submit/amend/delete orders acting as the vault
  • Any user can send funds to the vault to "invest" in it
    • When a user makes a new investment they will gain a share of the vault which is equal to the total amount of the vault asset across all accounts owned by the vault divided by the amount invested
    • When a new investment is made, the shares held by all other keys with existing investments are updated to to be their pro-rata share taking into account the new investment
  • see below comments for updated redemption logic Any user holding a share of the vault can request to redeem some or all of their share
    • Redemptions are marked as "pending" during the redemption delay period
    • Redemptions are processed automatically by transferring from the general account funds on the vault's key to the user after the redemption delay period, assuming the maximum redemption level hasn't been hit
    • If the maximum fraction has been redeemed, as much as possible (if anything) is redeemed and the remainder of the redemption is rolled to the next period. The redemption is marked as "held back" (or "throttled" or some better status?).
    • Redemptions are processed in the order received
    • If the vault does not have enough funds in the general account the redemption is marked as "late"
    • When there is at least one "late" redemption
      • the vault owner does not earn fees
      • any funds hitting the general account are immediately transferred to the party that is owed
  • Trading works as normal
  • Transfers and other transactions are not allowed

Key algorithms

Updating share

When a user funds the vault their share must be calculated and other users' shares must be updated.

existing_shares = [ ... ]

new_share = amount_invested / (total_value_of_all_vault_accounts_before_investment + new_funds_added)
existing_shares[i] = (existing_shares[i] * total_value_of_all_vault_accounts_before_investment) / (total_value_of_all_vault_accounts_before_investment + new_funds_added)

New gains

New gains are the amount of new value created since the last assessment (i.e. the end of the last fee period). If the relative performance of the vault is below its all time high, new gains will be zero. The algorithm below will allow correct calculation of new gains even in the presence of new subscriptions and redemptions.

A state variable high_water_mark is set to 1 at vault creation.

The "invested amount" is tracked as follows:

  • when funds are invested, invested_amount += new_funds_added
  • when funds are redeemed, invested_amount *= (1 - share_removed)

At the end of each fee period:

new_high_water_mark = max(high_water mark, total_balance_in_all_vault_accounts / invested_amount)
new_gains = min(0, new_high_water_mark - high_water_mark) * invested_amount
high_water_mark = new_high_water_mark
@barnabee
Copy link
Member Author

barnabee commented Oct 8, 2024

Open question: does there need to be a way to resterict the rate of adding funds?

Could be:

  • a parameter that sets the max % increase in vault NAV per period
  • new funds added go to a "waiting" account
    • funds are only counted as added to the vault, and the owner's share is only updated when explicitly transferred to the vault's general account by the vault owner (using a normal transfer tx)
    • if multiple keys have funds waiting it is done in order, i.e. the first key to fund the vault gets all their share added, then the next, etc. as more funds are moved from the waiting account)
    • a funder can cancel their subscription instantly while their funds are in the waiting account

If we do nothing I worry about the impact on returns if a vault grows too fast…

@0xfatman
Copy link

0xfatman commented Oct 8, 2024

I think everything looks great, except I would handle redemptions differently. This is how I envisaged them working:

Let's say someone has 1% share in a vault, and the vault has 100k in it, with 10k in the margin account and 90k in the general account, then...

  • This user's maximum redeemable amount would be 1k (e.g. if no funds are held on margin)
  • The vault owner can set the max redemption amount to be N% of the available funds in general account
  • Let's say N=20%, so this user can redeem 20% x 90k x 1% = 180 USDT in a single redemption tx
  • After redemption, this user's share of the vault = (1000 - 180) / (100,000 - 180) = 0.8215%
  • The user could then repeat this over and over, but:
    • Total free margin in the vault will be lower, and;
    • Their share of the pool will also be lower, meaning;
    • The amount that they can redeem will trend to zero over successive redemptions

I see this as beneficial because we don't need to require vault owners to define arbitrary delays, and we also don't need to handle the edge case where redemptions are not processed on time by the vault owner.

Oh lastly, I don't think it's a huge problem if vaults grow quickly, but maybe you have some common/likely use cases in mind that you think we should be concerned about?

@0xfatman
Copy link

0xfatman commented Oct 8, 2024

I suppose we could also have a network-wide restriction that means each user can only do one redemption per epoch. That would limit the user from the example above to 180 USDT in epoch 1, giving the rest of the vault depositors an opportunity to make redemptions from the available balance before this user is able to redeem again in the next epoch.

This would prevent a whale depositor from draining the available margin, while everyone else's money gets tied up supporting open orders and/or open interest.

@davidsiska-vega
Copy link
Contributor

  • When fees are paid, this is done by increasing the share of the vault's total assets attributed to the vault owner and decreasing the shares held by everyone else pro rata, meaning funds do not need to be available or moved between accounts to pay fees

Will need enough decimal precision not to lose this, especially if fee period is short.

@davidsiska-vega
Copy link
Contributor

  • The owner can update, close, or change the owning key of a vault

I am not sure we should allow updates to withdrawal delays, fractions, fees... only metadata. To "update" a vault, close it and open a new one - and advertise this in the metadata of the old one.

@davidsiska-vega
Copy link
Contributor

davidsiska-vega commented Oct 9, 2024

Needs anti-spam parameter of minimum vault investment quantum multiple or some such.

OR we may want a minimum for the party setting up the vault (as a quantum multiple) and then a minimum vault investment as a fraction of the total vault capital e.g. 1%.

@davidsiska-vega davidsiska-vega added this to the 🕌 Genbu Temple milestone Oct 9, 2024
@barnabee
Copy link
Member Author

barnabee commented Oct 9, 2024

Let's say someone has 1% share in a vault, and the vault has 100k in it, with 10k in the margin account and 90k in the general account, then...

  • This user's maximum redeemable amount would be 1k (e.g. if no funds are held on margin)

  • The vault owner can set the max redemption amount to be N% of the available funds in general account

I think limiting redemptions to the general account amount is potentially quite problematic.

The example is perhaps quite misleading because there's no reason in general that 90% of the funds in the vault would be in the general account. If this was somewhat guaranteed then obviously using only general account balance for redemptions would be more reasonable, but that's not a assumption we can generally make.

  • A vault owner can trivially engineer a low or zero general account balance (via e.g. isolated margin, AMM pools, etc.), thus keeping funds locked up for them to trade with forever.

  • Subscribers to the vault also need a way to signal that they want to withdraw all their funds, this should not be related to the general account balance. A vault my have one subscriber with 50% of the funds, for example.

  • This proposal also means that if there are lots of withdrawals quickly in a vault with a large general account balance, the vault owner could suddenly find themselves much more leveraged or restricted in their ability to trade, which the idea of a delay / redemption period is designed to avoid by giving notice.

The current design trades off safety for pragmatism somewhat, by not enforcing liquidations for late redemptions in the MVP but it would still ensure that as funds became available, redemptions are processed, and provide some incentive to do them on time in order to earn fees.

Happy to consider compromises or other alternatives if you really want to avoid a redemption period, but as it stands I'm not very comfortable forcing the size of redemptions to be bounded by the general account balance.

NB: the proposed design does include a maximum fraction of the vault that can be redeemed per period, and we could udpate that to be more like your proposed formula (e.g. x% times users share times vault value), and a user would be free to set this quite low and use a very short or zero delay if they wished.

@davidsiska-vega
Copy link
Contributor

One thing that I am not sure how I'd do but it would be nice if someone can certify their identity as a manager of the vault somehow. E.g. a Ethereum name service registered key can sign something that they can then add to the vault metadata to say hey, we here at fund X, it's really us and we're running the vault.

@barnabee
Copy link
Member Author

barnabee commented Oct 9, 2024

The example is perhaps quite misleading because there's no reason in general that 90% of the funds in the vault would be in the general account. If this was somewhat guaranteed then obviously using only general account balance for redemptions would be more reasonable, but that's not a assumption we can generally make.

@0xfatman the other option to make something like your proposal workable would be to specify a minimum % of the vault value that must be in the general account and prevent new orders that take the account below that.

I don't feel like it's a great solution. It'd need a mechanism to incentivise keeping to that minimum in the face of MTM losses (or to partially liquidate to do so) and would feel a bit hacky, and possibly be a pain to test, but it would be possible.

@barnabee
Copy link
Member Author

barnabee commented Oct 9, 2024

One thing that I am not sure how I'd do but it would be nice if someone can certify their identity as a manager of the vault somehow. E.g. a Ethereum name service registered key can sign something that they can then add to the vault metadata to say hey, we here at fund X, it's really us and we're running the vault.

Someone could sign a message with a Vega key and put it on their website / socials. The well-known repo could be used to track where these have been verified (it already is used for this for oracles) and then dapps like Console could query the repo to put a verification mark on vaults.

@barnabee
Copy link
Member Author

barnabee commented Oct 9, 2024

I am not sure we should allow updates to withdrawal delays, fractions, fees... only metadata. To "update" a vault, close it and open a new one - and advertise this in the metadata of the old one.

I believe amending withdrawal rules can be desirable as it may be hard to get these right ahead of time, particularly if the vault is going to do things where there may be low liquidity (e.g. be the only market maker on a market).

@davidsiska-vega what are your thoughts on allowing such changes but with certain rules, such changes only applying after a minimum time period?

Another option would be to specify specific redemption dates. For example if someone provided liquidity on futures they could allow redemptions after each settlement date.

@0xfatman
Copy link

@barnabee okay I didn't think about the scenario where a vault owner engineers a low general balance, in which case my suggestion doesn't work.

I think that leaves us with your original proposal being the most viable option, so would say let's proceed on that basis. However, I thought of another drawback with your original summary:

It doesn't work particularly well for illiquid markets, where e.g. >80% of the liquidity is provided by one vault. You assume that the vault owner is able to liquidate its exposure to facilitate withdrawals, which might not always be possible. I suppose in this scenario the vault owner will need to configure the vault to have very long redemption delays, but I just wanted to flag that this is a consequence of this design approach and see if anything else can be done to mitigate the impact this has on the UX for vault depositors.

@0xfatman
Copy link

The example is perhaps quite misleading because there's no reason in general that 90% of the funds in the vault would be in the general account. If this was somewhat guaranteed then obviously using only general account balance for redemptions would be more reasonable, but that's not a assumption we can generally make.

@0xfatman the other option to make something like your proposal workable would be to specify a minimum % of the vault value that must be in the general account and prevent new orders that take the account below that.

I don't feel like it's a great solution. It'd need a mechanism to incentivise keeping to that minimum in the face of MTM losses (or to partially liquidate to do so) and would feel a bit hacky, and possibly be a pain to test, but it would be possible.

I'm not keen on this solution. I'd go in the direction of your original proposal.

@barnabee
Copy link
Member Author

barnabee commented Oct 10, 2024

It doesn't work particularly well for illiquid markets, where e.g. >80% of the liquidity is provided by one vault. You assume that the vault owner is able to liquidate its exposure to facilitate withdrawals, which might not always be possible.

see if anything else can be done to mitigate the impact this has on the UX for vault depositors.

The issue here seems to be the existence of two very differerent types of vault. Roughly speaking they can be seen as analagous to:

  1. A liquid tradiing fund or ETF, in which it is possible to fairly easily allow buying into and out of the fund, because the assumption is that positions can always be exited or increaed easily. This is covered nicely by the redemption period design IMO.

  2. A more "venture-like" fund. In this case there may be no liquidity to exit positions outside of a defined schedule or some kind of liquidity event. This is not covered well yet.

To better cover the second type of vault, I propose modifying the model described above to a kind of hybrid design. Instead of a redemption waiting period starting at the time of the request (i.e. "continuous redemptions", there would be set redemption dates.

  • These dates are specified as a list containing explicit dates with their redemption and max. fraction (see below for definitions of both).

    • The list could also be allowed to contain rules with a start date, end date, and period length, which would be interpreted to create regular dates without having to provide a full list.
  • A redemption cut-off period is specified.

  • Any redemption request is queued and marked with status = pending until the next redemption date that is after now + cut_off_period_length.

  • Each date can be specified to be either a "normal" or "free cash only" redemption date, along with a maximum redemption fraction:

    • On a normal redemption date, subscribers may redeem up to a maximum redemption fraction of the vault's TOTAL balance (including margin accounts etc.). Their requests would be partially satisfied pro-rata if total redemptions requested are larger than the configured fraction. If there isn't enough in the general account to cover the queued redemptions on the next redemption date, the unpaid redemptions are marked as "late" and are paid back first any time funds hit the general account after that, until all redemption requests that were valid for that date are satisfied. While there are outstanding unsatisfied reqesuts, the vault owner would also not earn fees.

    • On a partial / free cash only date, every redemption request is satisfied as far as possible (pro-rata, so each subscriber gets the same % of their share redeemed, unless they requested less that what is available, in which case they receive the full amount) from the cash in the general account at the redemption date. The maximum amount that can be redeemed in this case is maximum_redemption_fraction × general_account balance. Any remainder of the redemption requests is cancelled and subscribers would need to re-apply for the next date.

  • The last redemption date is considered to be a "closing date". It is treated as if every subscriber has a full redemption request outstanding from that date. Funds hitting the general account would be returned to the subscribers pro-rata by their share. Subscribers do not need to manually request redemption for the final date.

  • Before the final date, redemption dates could be aded or removed, with some rules applied to prevent abuse. It should not be possible to remove upcoming dates that are less than some minimum notice period (a network parameter) from now, nor to remove the next upcomiong date even if it is more than the minimum notice period away, meaning pending redemptions will always go through on before the time expected by the user (if an earlier date is added).

I believe this design would satisfy both type of vault.

For a liquid vault, regular "normal" redemption dates would allow freely coming and going under most circumstances (with the max. fraction acting as a limit to avoid forcing painful liquidations to happen too quickly).

For a less liquid vault, dates for "normal" redemptions could be aligned with liquidity events and/or a long-dated "end date" for the vault (which could also be moved), and regular partial/free cash only dates would allow people to redeem more often if and when the cash is available.

@0xfatman @davidsiska-vega I'd be interested to know whether you think this model would work better?

@0xfatman
Copy link

Looks good to me

@cdummett
Copy link
Collaborator

cdummett commented Oct 25, 2024

Regarding APIs does the following sound like it gives users the ability to query everything they need @0xfatman @barnabee @davidsiska-vega

A vaults endpoint, exposing

  • a list of vaults

    • the vault id
    • the vaults status
    • all other vault parameters
    • a list of parties and...
      • their share of the vault
      • their current investment amount
    • next fee payment timestamp
    • next redemption timestamp (this may be superfluous if we are including all the redemption dates anyway)
  • filterable by

    • vault id

A redemptions endpoint, exposing

  • a list of redemptions, including

    • the party id
    • the vault id
    • the redemption status (pending / late / completed)
    • amount requested
    • amount received
    • timestamp requested
    • timestamp updated (updated rather than received as a late redemption may only partially pay out and then complete later).
  • filterable by

    • vault id
    • party id
    • redemption status
    • date range

@davidsiska-vega
Copy link
Contributor

It may be nice to have access to vault balance across all accounts for each asset, so the vault general + margin over markets with same asset + bonds over markets with same asset… so people can see at a quick glance how much their 3% (or whatever) of a given vault is actually worth.

@davidsiska-vega
Copy link
Contributor

Spam:

  • minimum deposit quantum multiple
  • minimum withdrawal quantum multiple
  • maximum number of deposits withdrawals per epoch per key

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants