Vaults and ERC-4624
Lets jump into this a little here....
While there are a couple of prominent token standards at the moment, the Decentralized Finance (DeFi) world still has a strong recurring problem regarding tokenized vaults. This led to the creation of the latest standard called ERC-4626.
This article will explain what vaults are, the problems that developers face in tokenizing them, and how ERC-4626 solves this problem in DeFi development. Then we’ll dive deep into the new changes this standard brings and show you how to implement them in your smart contracts.
What is a vault?
A vault is a multi-sig solution or smart contract that can store and manage assets such as crypto. Each vault always has the tokens it generates as a form of returns. These generated tokens can later be exchanged for tokens that were originally locked in vaults.
For example, when you stake Sushi on Sushiswap, which is an automated market maker (AMM), you will get xSushi as a reward. Similarly, you will also get cUSDC when you yield farm the USDC stablecoin on Compound, a DeFi borrow/lending protocol.
cUSDC and xSushi are yield-bearing tokens, which you can be redeemed in exchange for the original token (e.g. USDC or SUSHI in this example). The value of yield-bearing tokens will always increase so far as the locked tokens in the vault or pool increase.
Vaults are perceived to be better and more secure than wallets, and it is the reason many DeFi protocols choose to deposit their funds in a vault. Popular DeFi protocols that use vaults include Sushiswap, Aave, Balancer, and Compound among others.
What is the problem with tokenizing vaults?
The problem developers face concerning yield-bearing tokens is integrating tokens of different protocols.
For example, in a situation where you want to build a DeFi app where you’ll need to integrate the tokens of each protocol, you will need to research each one, know their model of accruing yields, and adjust it into your code base.
If you want to integrate vDAI of Maker DAO; stETH on Curve; and so on, you will need to understand the peculiarities of their smart contracts and build custom solutions to successfully integrate each of them into your DeFi app.
Apart from how stressful and time-consuming this process of integrating different yield-bearing tokens can be, it also increases smart contract risk because of potential errors.
Developers will need to spend more time checking for potential loopholes in the adapters, and in some cases, they might even need to outsource it to smart contract auditors, which can be quite costly. This is more important now that attackers are breaching the integrity of a lot of protocols and DeFi apps.
Who created the ERC-4626 standard?
Towards the end of 2021, noticing how it was difficult for developers to integrate separate yield-bearing tokens, Joey Santoro—founder of Fei Protocol—led a team of four other Ethereum developers to submit Ethereum Comment Proposal 4626 (ERC-4626).
After going through several rounds of review and deliberations, Ethereum finally approved the standard in May of 2022.
What are the benefits of ERC-4626 concerning vaults?
The main benefit of ERC-4626 is that it standardizes tokenized vaults to make protocol integration easier and less prone to error.
Since there is a common standard that you can integrate, there is no actual need to build separate adapters any longer. In a nutshell, it quickens development; composability at its peak.
Similarly, it reduces cost because builders no longer need to get auditors to help with their adapters and interfaces. Most importantly, ERC-4626 enhances security among dApps and yield aggregators that are dealing with yield-bearing tokens.
What changes does the ERC-4626 standard introduce?
With the new ERC-4626 token, there is now a standard for developers to build DeFi apps that involve yield tokens.
In a nutshell, the ERC-4626 standard implements the following features:
an optimized vault interface for developers who want to integrate it.
gives shares as an exchange for deposit where shares serve represent fractional ownership of the vault's underlying token
a consistent standard for developers to work with in developing yield-bearing contracts
battle-tested security for vault tokens
How ERC-4626 Works: Functions and Events
The ERC-4626 is an extension of and compatible with ERC-20 standard. As a result, most of the usual variables, events, and functions that are applicable in ERC-20 token contracts still work with the ERC-4626 vault standard.
The vault standard introduces the concept of shares as a way of getting fractional ownership out of the entire pool. These shares refer to yield-bearing tokens.
Now let's start developing in ERC-4626.
While you can use languages like Cairo and Viper, we will write this contract with Solidity.
1. Import OpenZepellin extensions into your IDE
After you have opened your IDE–we recommend Remix–instruct the compiler on the version of Solidity with which you’re writing the contract.
In this case, declare that you’ll be working with 0.8. After that, you’ll need to import two OpenZeppelin extensions of both ERC-20 and ERC-4626.
CopiedPragma solidity ^0.8;import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol";import "https://github.com/Rari-Capital/solmate/blob/main/src/mixins/ERC4626.sol";
Next, let’s create a contract and name it.
2. Create your contract
Name your contract and further entrench that it is based on both the ERC-20 token and ERC-4626.
Contract, testingVaults is ERC20, IERC4626 { your entire code here}
3. Implement the standard
After creating the contract, there are some important changes you should know about the methods, functions, and events in this standard. Thus, let's examine some of the methods and events in ERC-4626:
Deposit
When the users put any funds into the vault, the deposit function triggers the smart contract to mint a corresponding amount of shares to the depositor. As an event, the smart contract must be triggered whenever there is a deposit.
CopiedFunction deposit(address _to, uint256 _value) public returns (uint256 _shares)
With this function, we have instructed the contract to deposit some tokens into the vault and give the ownership of shares to the caller. You can write the withdrawal function the same way.
Withdrawal
The withdrawal function helps owners burn shares in exchange for assets. When there is withdrawal from the vault, the withdrawal event must be fired.
CopiedEvent Deposit(address indexed _from, address indexed _to, uint256 _value)
The address indexed _from in this event represents the user who approved the depositing of tokens to the vault, while the person who can withdraw the deposited tokens is the address indexed _to.
Asset and totalAsset
The address of the vault token should be used in the asset function. The entire amount of the underlying asset in the smart contract should be declared under totalAssets.
convertToShares and convertToAssets
Under the ERC-4626 standard, there are two functions of conversion: convertToShares
and convertToAssets
.
Where you need to convert assets to shares, convertToShares
is the right function to call because it contains the number of shares to release in place of the assets.
Conversely, convertToAssets
works the other way round by converting shares to assets.
CopiedFunction convertToAssets(uint256 shares) public view virtual override returns (uint256 assets) {Return _convertToAssets(shares, Math.Rounding.Down);Function totalAssets() public view virtual override returns (uint256) {Return _asset.balanceOf(address(this)); }
Mint
The mint function is called for the receiver once there is a deposit. maxMint
is the total amount of shares that can be created for a user or receiver in a vault. As a developer, you should set this.
CopiedFunction mint(uint256 shares, address receiver) public virtual override returns (uint256) { Require(shares <= maxMint(receiver), "ERC20TokenizedVault: mint more than max");
Redeem
The redeem
function burns some shares from the owner—msg.sender—and sends assets to the receiver. If it is the case that the shares cannot be redeemed, for one reason or another, redeem
must be reverted.
CopiedFunction redeem(address _to, uint256 _shares) public returns (uint256 _value)
maxRedeem
is the number of shares in the vault that the owner can redeem.
Preview
When using the preview methods, developers must bear in mind that the values the methods return won’t be quite exact, but they will be close. You shouldn't rely on them as oracles.
You can use preview alongside other methods like mint
, withdraw
, redeem
, and deposit
.
And that’s it. You’ve successfully started your development journey with ERC-4626!
Wrapping Up – The Future of ERC-4626
There is a new tide in DeFi with the advent of ERC-4626.
DeFi aggregators have always found it quite stressful to aggregate several yield-bearing tokens because there was no standard. But now ERC-4626 makes it possible to have details of yield-bearing tokens with one API call.
The problem of going the extra mile to enhance the security of DeFi applications with yield-bearing tokens is solved—to a large extent—with this battle-tested standard.
Use of composability and interoperability among various DeFi protocols will increase in the next couple of years. It is even possible that this standard will be a pedestal to building and shipping completely new products in the DeFi ecosystem.
Last updated