SIP-302: Funds (V3)

Author
StatusDraft
TypeGovernance
NetworkEthereum & Optimism
ImplementorDaniel Beal (@dbeal-eth), Leonardo Massazza (@leomassazza), Alejandro Santander (@ajsantander)
ReleaseTBD
Created2022-05-03

Simple Summary

This SIP proposes the creation of funds in Version 3 of the Synthetix protocol. Funds serve as an intermediary by accepting collateral from accounts and providing liquidity to markets.

Abstract

Funds can be created by anyone. Accounts can assign staked collateral to funds. Accounts can then mint and burn sUSD from a fund. The owner of a fund can optionally configure a staking position, which determines how the liquidity provided by staked collateral should be apportioned to the markets it backs. The fund tracks the debt responsibility of each account based on the sUSD that the account has minted or burned, and price fluctuations in the markets that it backs.

Motivation

By introducing the concept of a fund, we are able to allow stakers to customize their exposure while also allowing stakers to delegate the management of their staking position to others. We envision the creation of a fund that will be managed by the Spartan Council; the official user interface will have stakers delegate their collateral to this fund by default, allowing for a user experience similar to the current version of the protocol. There may also be a fund with no exposure to markets, allowing users to mint and burn USD without exposure to debt from price fluctuations in markets. This should allow the sUSD supply to be increased with little or no risk.

Funds may also serve as the entity for facilitating cross-chain synthesis. Because the proposed architecture for version 3 separates the debt pool into individual markets, we envision relying on an oracle to concentrate liquidity between funds across networks.

Specification

Overview

The implementation of funds involves the following considerations:

  • Creating Funds
  • Delegating Collateral
  • Minting and Burning sUSD
  • Configuring Staking Positions

Rationale

Funds create a clean abstraction for provisioning liquidity and sUSD issuance. An alternative approach could involve a separate contract for managing all collateral in the system, another contract to manage minting and burning sUSD, and then allowing accounts to provide liquidity directly to markets. This is not desirable because it adds unnecessary components to the system and significantly increases the implementation complexity of features like delegated staking positions.

It may seem as if we could allow funds to decide which types of collateral are acceptable, rather than configuring this across the entire protocol. This is not an option because we want to allow sUSD to be fungible (regardless of the fund from which it was minted). In other words, we need to prevent the creation of a fund that accepts low quality collateral, exposing all sUSD holders to that risk.

We also considered scoping in functionality that would allow a fund creator to prevent others from joining a fund without permission. This has not been included as this would only inconvenience users, given that a fund’s staking position is transparent. This will be revisited in future SIPs which address liquidations.

Technical Specification

Funds will implement the following interface:

IFund {
	function createFund(uint requestedFundId, address owner);
	function accountFundDebt(uint fundId, uint accountId, address collateralType);
	function fundDebt(uint fundId);
	function totalDebtShares(uint fundId);
	function debtPerShare(uint fundId);
	function collateralizationRatio(uint fundId, uint accountId, address collateralType);
	function delegateCollateral(uint fundId, uint accountId, address collateralType, uint amount, uint exposure);
	function mint(uint fundId, uint accountId, address collateralType, uint amount);
	function burn(uint fundId, uint accountId, address collateralType, uint amount);
	function rebalanceMarkets(uint fundId);
	function setFundPosition(uint fundId, uint[] markets, uint[] weights);
	function nominateFundOwner(uint fundId, address owner);
	function acceptFundOwnership(uint fundId);
	function renounceFundOwnership(uint fundId);
}

Creating Funds
Funds can be created by anyone using the createFund() function. The owner (and only the owner) has the ability to update the fund’s staking position (by calling setFundPosition()) and nominate a new owner for the fund with nominateFundOwner(). The nominated owner can call acceptFundOwnership() to become the owner. An owner can also call renounceFundOwnership(), effectively making the fund’s position permanent.

Delegating Collateral
Stakers can call the delegateCollateral() function, which will automatically create or update the relevant CollateralEntry (specified below) based on the provided parameters. It then triggers the rebalanceMarkets() function to notify each of the markets that the amount of liquidity available has changed. Stakers may only unassign collateral if the resulting C-Ratio is above the Target C-Ratio for that collateral’s type.

struct CollateralEntry {
	uint accountId;
	address collateralType;
	uint collateralAmount;
	uint leverage;
	uint initialDebt;
	uint withdrawn;
	int usdBalance;
}

Minting and Burning sUSD
Accounts may mint and burn sUSD backed by a collateral type that they have staked. sUSD is an ERC-20 token (with permit functionality) that is accepted by the market manager.

Minting and burning will increase and decrease the usdBalance value, respectively. Stakers may only mint sUSD if the resulting C-Ratio is above the Target C-Ratio for the relevant collateral type.

Configuring Staking Position
The owner of a fund is able to invoke the setFundPosition() function with an array of markets and their corresponding weights. For example, assigning the sBTC market a weight of 1 and the sEUR market a weight of 2 would indicate that one third of the liquidity in this fund should be provided to the sBTC market and two thirds should be provided to the sEUR market. rebalanceMarkets() is called whenever the staking position of a fund is manipulated.

Test Cases

Relevant tests will be developed during implementation.

Configurable Values (Via SCCP)

  • Preferred Fund (uint) - This is the ID of a fund which the Spartan Council prefers that stakers join. This will be the default fund for stakers in the official UI.
  • Approved Funds (uint[]) - This is a list of funds’ IDs owned (or otherwise approved) by the Spartan Council and will be listed in the official UI.

Copyright and related rights waived via CC0.