Virtually all lending/borrowing protocols are permissioned. Governance or developer intervention is required to support new tokens, etc. There is an important exception to this rule: Fuse. In this article, we’re going to to cover a high level overview of the Fuse protocol ecosystem. Buckle up, kiddos. We’re going on a trip.
First, a bit of background. Compound is one of the earliest DeFi lending protocols on Ethereum. It’s still going strong today, and is responsible for laying a lot of groundwork in the space, particularly with respect to governance. The Compound Governor Bravo design is one of the most widely used patterns for strongly on-chain governance schemes. (See also: Governance Attacks and You)
There’s only one problem: Compound is permissioned. Everything from managing rates to supporting new assets happens through the governance process.
Enter Rari Capital. Rari’s flagship product, Fuse, is essentially a permissionless fork of Compound. They share much of the same architecture, but Fuse has the ability for third parties to create and operate lending pools as they see fit.
Note: Rari Capital was subsequently taken over in a friendly merger by Fei Protocol so please note that when I mention Rari in this article.
There’s a lot to cover here to comprehend the architecture, so let’s dive in to some foundational material. You may want to take notes. The Fuse team has done a good job of documenting the user borrow/lending flows, but I struggled to find a holistic overview of the entire protocol. Finally I decided to make the overview myself, and here we are.
If you grasp this article, you’ll understand Fuse better than 99% of users!
Fuse’s model works off the backbone of the Compound model, so let’s cover a little bit of that first. As a reminder, Compound is a borrowing and lending protocol. You can deposit assets, earn interest on them, and then borrow against those assets.
Compound Model: cTokens
Fuse Tokens (fTokens) are the Fuse branded variant of the Compound cToken. Each fToken has one underlying asset, which can be either Ether or an ERC-20 token. You can deposit the underlying asset into this contract, and borrow the underlying asset from the contract.
The fToken is the heart of the entire arrangement, because it is fundamentally how you earn interest, and how you borrow. The fToken is a yield-bearing token, which works on the idea of an exchange rate.
Let’s say I deposit 100 DAI into a DAI fToken contract, and the current exchange rate is 0.5 DAI/fDAI. I will receive back 200 fDAI. Over time, the exchange rate goes up. Say I let it sit until the exchange rate reaches 0.51 DAI/fDAI. When I redeem my 200 fDAI, I get 200*0.51 = 102 DAI back, for a 2 DAI profit.
There is a separate interest rate for borrows. Each block, the incremental new interest is added to the debt balance which has to be paid off before you can redeem your collateral. The interest rate calculation happens anytime someone makes a state-modifying transaction to the protocol, like borrowing or redeeming fTokens.
Compound Model: Comptroller
The comptroller is the brains of the operation. The fTokens delegate important questions to the comptroller, such as “is this user allowed to withdraw their collateral?”, or “can this user transfer this fToken, or is it locked up being used as collateral?”.
Why is this functionality not included in the fToken contract? Good question! Each fToken only deals with one asset. You have fDAI, fUSDC, etc. What if I want to deposit DAI, but borrow USDC? That’s where the comptroller comes in. It integrates data from all the fTokens under its domain, and takes it all into account when determining whether operations are allowed.
So if I deposit DAI, and borrow ETH and SUSHI against it, both the ETH and SUSHI position values will be taken into account when determining if I can borrow something else against the DAI.
When you provide collateral into a Compound model, that liquidity is credited to your account in total. You can borrow any asset which has an fToken under that comptroller. There is no ability to segment it off, eg. the protocol can’t prevent you from using your SHIB collateral to borrow ETH, as long as they both have fTokens under that comptroller.
TL;DR: Each fToken asks the comptroller “is this allowed” before it does any action. The comptroller takes in information from all fTokens in its charge and decides yes/no.
The cTokens and comptroller form the basic building blocks of the Compound model. There are also helper contracts and governance which we’ll get into later.
The Compound model has one critical weak point. Its risk is not isolated. What I mean by this is that if one token in the Compound ecosystem is vulnerable, all the other assets are vulnerable by extension.
Say Compound adds some arbitrary new token, Token A. Down the road, Token A is hit by an infinite mint bug, and the hacker dumps quadrillions of tokens of Token A into Compound. They can then borrow against that mass of Token A and drain the protocol of valuable tokens like ETH, DAI, etc.
This method of exploiting one token and using it to borrow valuable tokens is an extremely common attack pattern, and it continues to plague lending protocols today.
Compound mitigates this risk by an extremely rigorous governance process. The DAO is active, highly involved, and only well-tested, audited tokens are allowed entry.
Rari Capital had to handle this issue when they attempted to make a permissionless Compound. If you remove governance and anyone can add assets to the system, the only protection against loss is gone. To solve this, Rari created the idea of Fuse Pools.
Each Fuse pool is its own, self-contained Compound ecosystem. The creation of a Fuse pool is permissionless. The creator of a Fuse pool gains administrative rights over it, and can implement governance within the pool however they wish.
The key distinction is that the pools are isolated from each other. Pool 1’s comptroller does not talk to Pool 2’s comptroller and vice versa. So, any issues in one pool cannot impact funds in other pools. The risk is isolated.
The Fuse ecosystem then essentially looks like this:
TL;DR: Fuse is essentially a universe of miniature Compound forks.
To make the deployment of these mini-Compounds permissionless, two main things are needed:
- A way to trustlessly deploy exact copies of the smart contracts
- A way to keep track of the deployed pools
This need is filled by the FusePoolDirectory contract. In more general terms, this smart contract is a contract factory.
Design Pattern: Contract Factory
There are two major properties of smart contracts which make this pattern possible.
- They are immutable. (Unless very specific design features are used, and even then their mutation is limited)
- Smart contracts can deploy other smart contracts.
These two properties together means that a smart contract can be given a code payload, and repeatedly, trustlessly deploy that code to the blockchain as a shiny new contract.
In the case of Fuse, the FusePoolDirectory is a contract factory responsible for deploying new comptrollers. And, since it’s creating them, it’s easy to initialize them with all the right parameters, and register all that info in one central location.
TL;DR: The FusePoolDirectory serves to both trustlessly create and centrally register new Fuse pools.
Lending and borrowing protocols have interest rates. That much should be self-evident, and if it’s not, you should probably be in a basic macroeconomics class instead of reading this article.
Interest rate models for DeFi are important, as they are one of the main policy levers retained by governance. Good interest rate models promote healthy utilization of funds and keep markets efficient.
You can imagine that different assets should probably have different interest rates. Something like Ether does not have the same inherent risks that a new DeFi protocol token has, and so should not carry the same risk premium.
You can also imagine that the design of your interest rate mechanism can help promote desired use of the protocol. One common model is the jump rate model, where there is a “kink” in the interest rate curve at higher protocol utilization (amount of borrows / amount of cash on hand). This serves to increase the cost of borrowing at high utilization, where the protocol has less margin against the event of a price collapse, etc.
There’s a lovely interactive calculator on Observable here, which you can use to play around with different common interest rate models.
From this discussion, you can probably gather that interest models need to be highly flexible. This presents a problem. You can’t custom code all this functionality in the fToken contracts, or they will become bloated and vulnerable – not to mention inefficient. It’s also very hard to do custom interest rate models hardcoded in each protocol permissionlessly.
To deal with this, the Compound developers produced a very interesting innovation, which Rari continued to use for Fuse.
Design Pattern: Interest Rate Models
The solution to the interest rate calculation problem is to abstract the math out from the fToken contracts and into its own, separate contract. When an fToken is set up, it is passed the address of its interest rate model. Then, whenever it needs to calculate interest, it will shoot off a transaction to the interest rate contract, and receive back the correct numbers.
The best part about this? Multiple tokens can use the same contract to implement their interest rate math, saving on gas costs. It’s also permissionless, allowing users to pick the interest rate model best suited to their needs without having to custom code and deploy it.
TL;DR: fTokens have a standardized way of passing data and requesting to perform interest rate calculations on it. Different interest rate models adhere to that standard interface, but implement different underlying math.
The multi-layered design of Fuse as a whole can make it challenging to parse data. A user can be in multiple fTokens, across multiple Fuse pools. Retrieving this data manually can be quite prohibitive.
This data layering also presents issue for liquidations. Overcollateralized lending protocols (like the Compound model) rely on timely liquidations to maintain borrow health. If a user’s position falls below the allowed amount, someone else can come in, pay back a portion of the user’s debt, and take the user’s collateral plus a fee.
Finding users with poor borrow health and preparing a transaction to strike at them through multiple layers of data is not easy to do on your own. Rari implements two peripheral contracts to help with these issues.
These contracts are not part of the core borrow/lend mechanism, and the protocol can function without them. However, they are immensely helpful, and smooth user experience.
The Fuse Pool Lens
The Lens is a smart contract specialized in retrieving data across all pools and fTokens. There are a lot of functions you can use to retrieve different slices of this data.
Note: The Lens is designed to be used by offchain sources. Performing any of these calls onchain is going to be exorbitantly expensive due to the amount of memory that has to be accessed, and may even fail due to out of gas. Users are supposed to call these view-only functions, digest the data offchain, then feed the inputs to their smart contract to do whatever it needs to do.
The FuseSafeLiquidator contract provides an easy interface to perform liquidations. Rather than having to make your own smart contract to liquidate assets, the FuseSafeLiquidator has everything set up for you. Just feed it the data (helpfully obtained via the Lens) and let it rip.
The liquidator contract also allows liquidation via flash loan, for increased efficiency.
Check-in and Recap
That’s a lot to digest, so let’s rally here for a moment. The primary Fuse architecture as we understand it now looks like this:
Where we have the core contracts (directory, the individual comptroller/fToken arrangements in each pool), as well as the peripheral contracts (liquidator, lens) that don’t directly participate in the core logic, but are still essential to the smooth function of the business model.
Not pictured in that diagram are the interest rate models referenced by the fTokens. Remember, each fToken can only use one interest rate model, but multiple fTokens can use the same model.
We’ve covered a lot, but there’s still a lot to go over!
- Proxies and implementations
- Governance of individual Fuse pools
- Fee flows and value accrual
Rehydrate, stretch your legs, and let’s dive into round 2.
Smart contracts are immutable by nature. There are a few exceptions to this (CREATE2 opcode, etc) but those are outside the scope of this overview. Immutability is great. It enables trustless operation, since you can verify that the code of a protocol won’t change underneath you.
Immutability can also be a risk factor. What if a bug is discovered in your protocol? With immutable contracts, you have to safely perform a migration of user funds to an upgraded contract. This is slow, extremely complex, and fraught with risk.
If there is a way to allow limited upgrades to your protocol, you can patch the bug in production and no one is impacted.
The most common way to implement this is an upgradeable proxy pattern.
In this pattern, you have a single point of entry, which is the proxy contract. The proxy contract does only two things. 1) it stores the state of your contract. Account balances, blacklists, earned rewards, active users, etc. 2) it forwards all function calls to the implementation contract, which contains the logic and code.
There is an additional actor, the proxy admin, who has the authority to change which implementation contract the proxy directs its calls to. The implications of this pattern are that you can change out the implementation logic of your contract (such as to fix bugs or add new features) without changing the state (like user token balances).
Obviously, making code mutable has some security implications. Access to the ability to change the implementation needs to be tightly controlled.
Proxies in Fuse
Most of the contracts in Fuse are actually upgradeable proxies. This grants gas savings, since the proxies are much, much smaller than the implementations.
The lens and directory are also proxy patterns. The interest rate models are not, as they are relatively cheap, and also reusable.
Here’s a rather simplified total diagram. Now you can start to see what a spaghetti this ends up being in practice.
To make it even more complex, the upgradeable function is optional when creating a Fuse pool. So some will be upgradeable, but others will not be!
Fees and Fund Flow
Fuse pools extract one or two fees. Both are incurred on the interest paid by borrowers.
The first fee is the protocol fee. This is a default 10% fee paid to the Rari treasury multisig wallet. Governance is allowed to decrease this fee on an individual pool-by-pool basis.
The second fee is the admin fee. This is an optional fee which the admin (governance entity for an individual Fuse pool) can choose to set.
For example, suppose a user borrows 100,000 DAI, and interest accumulates over time until his total amount owed is 110,000 DAI. If we assess the standard protocol fee, plus a 5% admin fee, the Rari treasury will receive 1,000 DAI, and the admin will receive 500 DAI.
There are a lot of parameters that can be set when launching a Fuse pool. I’ll refer you to the documentation for a full list. Admins can set the allowed assets, protocol parameters, price oracles to be used, etc.
For an example, let’s look at Fuse Pool 6, aka. Tetranode’s Locker. This is a popular pool administered by the anonymous DeFi kingpin Tetranode. Look at the “Info” tab and you can see the major settings.
Clicking the “Metrics” button takes you to a dashboard with a dizzying array of information on the pool’s health and statistics.
The comptroller for Pool 6 can be viewed here. On the “Contract” → “Read As Proxy” tab on Etherscan, you can view and verify some overarching parameters of the pool. (For a reminder of how to use Etherscan to read proxies, see Basic Rug Protection)
Wrapping Up The Fuse Protocol Overview
Congratulations on making it through this big, juicy post! In conclusion, here’s the final Fuse Protocol overview diagram for the entire ecosystem.
Here’s a final list of key takeaways:
- Compound is a lending/borrowing framework
- The Compound model uses an array of yield-bearing token contracts, integrated together by a comptroller
- Fuse is a permissionless way to deploy and govern mini-Compounds called Fuse Pools
- The risk in one Fuse Pool is isolated to that pool and does not affect any others
- Fuse pools can be governed by their respective Fuse Pool administrator
I hope you found this article helpful! Please let me know if you have questions.
Good luck out there, anon.