Trustless token management with Set Protocol
How to integrate token sets in your contracts
With Set Protocol you can create baskets of tokens that give users different levels of exposure to underlying assets (currently only ERC-20 tokens).
Set Protocol and their TokenSet
functionality is the perfect example for making use of the new paradigm of Defi and composability. You can let someone else manage your tokens for you, but they cannot steal all your funds. Of course there is some level of trust involved that the manager generally acts in the best interest of every Set participant, but since he receives fees from participants and has no direct monetary gain, the risk is minimized.
So what is Set Protocol?
With the Set Protocol you can enable passive managements for ERC-20 tokens on Ethereum. A given set is managed by one or multiple managers that can employ different strategies based on the functionality added to this set. The system is designed in a modular way allowing you to choose which functionality in the form of modules to add to a set. In the future all of the governance inside Set Protocol will be fully decentralized.
Let's explore the relevant components of the underlying protocol...
1. The main contract: SetToken
The ERC20 Token contract that allows privileged modules to make modifications to its positions and invoke function calls from the SetToken.
You would create a new SetToken with the SetTokenCreator factory. You can call create
and pass
- a list of ERC-20 addresses (
_components
) - a list of quantities for each given token (
_units
) - a list of modules to be used (
_modules
) - the manager address (
_manager
) - the name of the set (
_name
) - the symbol of the set (
_symbol
)
function create(
address[] memory _components,
int256[] memory _units,
address[] memory _modules,
address _manager,
string memory _name,
string memory _symbol
) external returns (address)
A concept of virtual and real quantities exist for efficient updating. It's essentially just a multiplier that exists inside the SetToken. A real unit value is calculated as realUnit = positionUnit * positionMultiplier
. This would allow updating the multiplier to change the real values of each component very efficiently.
2. Additional data contracts: Resources
Resources are contracts that provide data, functionality, or permissions that can be drawn upon from.
Those include most notably the controller, registry and price oracle.
A. System Controller
The controller is the master manager contract and can be used to
- Add/Remove Modules
- Add/Remove Factories
- Add/Remove Resources
- Remove SetTokens
- Add/Edit/Change Fees
- Edit Fee Recipient
The owner of the controller will eventually be a DAO, thus allowing decentralized governance of sets. Currently it's still a multi-sig contract.
B. Integration Registry
The IntegrationRegistry is used to manage external integrations, like support for the Aave system or an external DEX.
Governance can use this to:
- Add/Edit/Remove Integrations
C. Price Oracle
The PriceOracle returns a price for a given token pair. The price is retrieved either directly from an oracle, calculated using common asset pairs, or retrieved from external data.
The governance is allowed to
- Add/Edit/Remove Oracles and Adapters
3. Modules
Modules can be added to a SetToken and enable extra functionality. Th modules are optional additions to a SetToken and can be added or removed from a set by the manager.
Let's take a look at three common modules.
A. Basic Issuance
The Basic Issuance module allows users to mint (issue) and redeem a SetToken. The basic flow for this module is:
For each component inside the _setToken
, do
- Retrieve ERC-20 address.
- Retrieve required quantity given the passed
_quantity
. - Transfer quantity of given ERC-20 to the SetToken address from sender.
Lastly mint _quantity
SetToken tokens to the passed _to
address.
The respective redeem
function works similarly the other way around and burns the SetTokens again.
function issue(
ISetToken _setToken,
uint256 _quantity,
address _to
) external;
function redeem(
ISetToken _setToken,
uint256 _quantity,
address _to
) external;
B. Trade
The Trade module adds powerful trading functionality to a Set. However you will have to write your own integration for whichever market you want to trade on or you can use the existing Kyber integration.
The trade function can be called to execute a trade for a given SetToken. You will essentially sell the given sendToken in the sendQuantity for the receiveToken. Obviously the token you want to sell must actually exist in the SetToken in sufficient quantity.
Only the token manager may call the trade function.
If you want to write your own DEX integration, have a look at the KyberExchangeAdapter.
function trade(
ISetToken _setToken,
string memory _exchangeName,
address _sendToken,
uint256 _sendQuantity,
address _receiveToken,
uint256 _minReceiveQuantity,
bytes memory _data
)
C. Tokenset Governance
Tokens these days are commonly used for governance as well, just remember when we look at the COMP governance. This is exactly what you can do with the Governance Module. Intended governance protocols are Compound, Uniswap and Maker, but theoretically any system that complies to the same functions could be used here.
The functionality includes
delegate
: Delegate voting power.propose
: Create a new proposal.vote
: Cast a vote on a proposal.
For more details on those functions and governance, take a look at the above mentioned COMP governance article.
Once again only the manager of the TokenSet may call any of those functions.
4. Rebalancing Sets
One interesting feature of sets is rebalancing. Usually with any assets you have the ratio of exposure you get from them can change dramatically over time given the price changes. Just imagine you have three tokens of projects you really like. Let's call them SuperCoolToken, SuperInterestingToken and SuperUsefulToken. You think all projects at the time of investing are valued at equally good prices, so you choose an even split of 33%.
Now you create a TokenSet with
- 33% SuperCoolToken
- 33% SuperInterestingToken
- 33% SuperUsefulToken
Now after a few months, SuperCoolToken mooned and went 10x, while SuperInterestingToken stayed the same and SuperUsefulToken actually went down by 50%. Your ratio now would be
- 87% SuperCoolToken
- 9% SuperInterestingToken
- 4% SuperUsefulToken
But you might still think all projects are still equally promising. Or you just want a more diversified exposure. In this case, wouldn't it be useful to have a mechanism automatically rebalance it to the original ratio?
It's explained in further details inside the Whitepaper. However, I'm curious as to what the current state for this is.
According to the Whitepaper the rebalancing works either via automated trading on DEX's or a system internal dutch auction. I can already see a rebalance overview site on https://www.tokensets.com/rebalance which is in fact listing auctions. However I could not find any smart contract code in the repository which contains the auction code. So if you know what's going on, please let me know.
There is however one module called SingleIndexModule which can be used for rebalancing functionality. It doesn't start auctions, but uses the defined DEX's to initiate a rebalancing.
There you have it, I find Set Protocol a fascinating idea and looking forward to where this develops in the future. Have you used Set Protocol before as a user? Or have you even interacted with the contracts directly? Let me know in the comments below.
Solidity Developer