Introduction
This document is intended for developers who wish to programmatically route crypto assets from other protocols to and from Vesper pools and strategies. It is a companion to the Vesper Contracts API Reference, which documents API end points for Vesper pools and Vesper strategies.
This Developer's Guide is not a guide to developing, testing, deploying or updating Vesper pools or strategies. As such it does not explain the programs (generally written in JavaScript) that are used by pool-operations to perform these functions. Also, it does not explain the inner workings of every strategy. Rather, it explains the overall architecture in which Vesper pools and strategies interact, and to give a conceptual overview of the role of each contract in the system. The purpose of this documentation is to enable developers of other protocols, DAOs, wallets, and other entities the opportunity to use Vesper, with confidence, for enhanced product offerings and treasury management options. For a complete understanding, of course, you should read the code itself in the Vesper repository. Think of this guide as your road map to what you'll find there.
The discussion that follows assumes that you've read Vesper's Modular Pool Architecture, which explains pool and strategy architecture in abstract terms. Below, we will go into more concrete detail to explain how this architecture is implemented in Vesper's smart contracts.
Categories of Vesper Smart Contracts
Vesper smart contracts, written in the Solidity programming language, are organized in the Vesper code repository in directories described in the next sections. The Vesper Contracts API Reference only documents contracts that reside in the Pool directory, along with a few key contracts in the Strategy directory, since those are the only ones that other (that is, external to Vesper) protocols would interact with. The types of Vesper smart contracts which exist in the repository but are not included in the Reference are described briefly below.
Dependencies
Wherever it is practical to do so, Vesper uses smart contracts from OpenZeppelin to implement common DeFi functionality. Contracts from OpenZeppelin are in the 'dependencies' directory.
Interfaces
Interfaces are pure abstract contracts that contain external functions that contain only declarations — that is, no statements. Implementations of other contracts inherit from them. The Interfaces directory includes Vesper interfaces from which pools and strategies are derived. Examples include IVesperPool.sol, IStrategy.sol, and IEarnDrip.sol.
Pool
This directory includes all the contracts that are instantiated when a Vesper pool is deployed. Each of these contracts is described in the Vesper API Reference.
Strategies
This directory includes all the strategy contracts employed by Vesper pools to generate yield. The contracts in this directory include both general purpose contracts like Strategy.sol and VesperStrategy.sol that are inherited by all strategy contracts, and contracts that implement specific strategies on specific platforms — for example the aave subdirectory includes the contracts AaveCore.sol, AaveLeverageStrategy.sol, AaveStrategy.sol, and so forth.
Test
This directory includes interfaces and contracts that are used to implement various tests.
Upgraders
This directory includes contracts that are used to upgrade pools and their related contracts.
Utils
This directory that contains contracts used to do things like interfacing with external exchanges.
Various Contracts at the Top Level of the 'Contracts' Directory
Contracts including Errors.sol, the abstract contracts FlashLoanHelper.sol, Governable.sol and Pausable.sol are implemented by all pools to provide common functionality.
Understanding Proxied Pools
We have seen that Vesper pools are engineered for upgrading. Not only can pool logic be changed to fix any errors or to improve performance, but also the strategies used by pools can be changed or modified at any time. This is accomplished using proxies, as explained below.
Note that although OpenZeppelin offers contracts to implement proxies, Vesper uses its own implementation of this concept not OpenZeppelin's.
The idea behind proxies is separating the logic parts of a pool from its state. Consider the illustration below. Imagine that we were going to implement a Vesper Grow pool for the 'Cool' token. The vCool pool would be created as an instance of Strategy.sol. When deployed, it would create two new contracts: the Logic Layer Contract, or llc, which contains the pool's logic, and the Storage Layer Contract, or SLC, which contains the pool's state. Thereafter, the storage layer contract effectively is the pool, from the point of view of other contracts that interact with it. In other words, if you were writing a contract on a protocol external to Vesper and wanted to invoke, say, the withdraw method of the vCool contract, you would access it at address A1, not A0.
Note that in the illustration below, the arrows from the vCool pool only point in one direction. This indicates that the pool contract spawns the SLC and LLC, but those contracts, once created, have no interaction with the pool contract.
The storage layer contract, in turn, contains a pointer to the address of the logic layer contract. The logic layer actually contains the code that implements the function that was invoked.
Given this architecture, the process of upgrading a pool is simply a matter of deploying a new LLC, and then changing pointer in the SLC to point to the new LLC instead of the original one.
Last updated