Hyperdrive System Architecture
Overview
In order for Hyperdrive to be widely used as a DeFi primitive, it is important that Hyperdrive pools can be discovered on-chain, configured with oversight from governance systems, deployed and initialized by anyone, and rated in a standard way to make it easy to consult expert knowledge on the risks of using different pools. Along with these goals, it is convenient to have a single entrypoint where users can deploy and initialize pools for all of the different implementations of Hyperdrive that will be required to support different yield sources. While the Hyperdrive AMM is the most significant component of the Hyperdrive protocol, there are several other components that facilitate these higher level goals. This document explains these ancillary components and the core flows associated with them.
System Components
Several independent contracts are used to achieve the goals of flexibility, discoverability, governance oversight, and standardized ratings. From the highest level to the lowest, the contracts in the system are registries, factories, deployer coordinators, deployers, proxies, and targets. Each layer consumes the layer below to accomplish its goals.
Registries
Hyperdrive registries are the contracts that provide users and protocols with ratings of the risks associated with different Hyperdrive pools. In theory, these registries could range in complexity from a whitelist of Hyperdrive addresses administered by a firm's multi-sig wallet to systems that provide more granular ratings to Hyperdrive pools based on the configuration used and underlying yield source. In contrast to some of the other systems of the Hyperdrive protocol, only a bare-bones implementation of a Hyperdrive registry and an interface for Hyperdrive registries has been included in the scope of this audit. If users and protocols end up requiring information from these registries, external parties will begin implementing their own registries to satisfy their requirements.
Core Functionality
The view function getHyperdriveInfo
accepts the address of a Hyperdrive instance and outputs a uint256
that indicates the health score the registry assigns to the pool. In the case of HyperdriveRegistry
, the output is binary and reflects whether or not governance has whitelisted the pool.
Related Contracts
contracts/src/interfaces/IHyperdriveRegistry.sol
contracts/src/interfaces/IHyperdriveGovernedRegistry.sol
contracts/src/factory/HyperdriveRegistry.sol
Factories
Hyperdrive factories are used by governance systems to register the deployer coordinators for different Hyperdrive implementations, maintain a set of sane guards on the configurations used to deploy new pools, maintain a set of admin configurations like the governance address, fee collector, and governance fees used by deployed pools, and collect the addresses of all of the pools that have been deployed. All of this functionality makes them a convenient way for deployers to deploy and initialize new Hyperdrive pools in such a way that the new pool is discoverable and configured with the parameters that satisfy the governance system's standard. By allowing deployers to atomically deploy and initialize pools, the factory also eliminates the risk that a deployer will be front-run in initializing a pool that they deployed. The current intention is for there to only be a single Hyperdrive factory per governance system, but it's unlikely that the current implementation is flexible enough to support all future Hyperdrive versions.
Core Functionality
Governance can transfer the governance role to another address with the updateGovernance
function.
Governance can update the admin configurations like the feeCollector
address and the hyperdriveGovernance
address (the address used to govern new Hyperdrive pools) with the following functions:
updateFeeCollector
updateHyperdriveGovernance
updateLinkerFactory
updateLinkerCodeHash
updateDefaultPausers
Governance can update the guards that are applied to the configurations of potential pools with the following functions:
updateCheckpointDurationResolution
updateMinCheckpointDuration
updateMaxCheckpointDuration
updateMinPositionDuration
updateMaxPositionDuration
updateMinFixedAPR
updateMaxFixedAPR
updateMinTimeStretchAPR
updateMaxTimeStretchAPR
updateMinFees
updateMaxFees
Governance can add new deployer coordinators for new Hyperdrive implementations with addDeployerCoordinator
and remove deployer coordinators for existing Hyperdrive implementations with removeDeployerCoordinator
.
Users can access the current parameters of the factory with the following functions:
governance
hyperdriveGovernance
linkerFactory
linkerCodeHash
feeCollector
checkpointDurationResolution
minCheckpointDuration
maxCheckpointDuration
minPositionDuration
maxPositionDuration
minFixedAPR
maxFixedAPR
minTimeStretchAPR
maxTimeStretchAPR
minFees
maxFees
defaultPausers
Users can check if an address is a registered deployer coordinator with isDeployerCoordinator
, get the number of deployer coordinators with getNumberOfDeployerCoordinators
, get the deployer coordinator at a particular index in the _deployerCoordinators
array with getDeployerCoordinatorAtIndex
, and get the deployer coordinators within a range of indexes in the _deployerCoordinators
array with getDeployerCoordinatorsInRange
.
Users can check if a given hyperdrive instance was deployed by the factory with isInstance
, which deployer coordinator (if any) deployed a given hyperdrive instance with instancesToDeployerCoordinators
, get the number of deployed hyperdrive instances with getNumberOfInstances
, get the hyperdrive instance at a particular index in the _instances
array with getInstanceAtIndex
,and get the hyperdrive instances within a range of indexes in the _instances
array with getInstancesInRange
.
Related Contracts
contracts/src/interfaces/IHyperdriveFactory.sol
contracts/src/factory/HyperdriveFactory.sol
Deployer Coordinators
Hyperdrive deployer coordinators abstract away the details of deploying specific implementations from the factory so that users can deploy pools with any of the factories registered implementations using the same functions in the Hyperdrive factories. Due to code size limitations, deployer coordinators rely upon underlying Hyperdrive deployers to deploy the components of a properly-configured Hyperdrive instance. The Hyperdrive deployer manages the deployment lifecycle by ensuring that all of the components of the Hyperdrive instance utilize the same configuration and by ensuring that all of the components of the Hyperdrive instance have been deployed successfully prior to considering the deployment to be complete. The deployment lifecycle can be completed over the course of several blocks to avoid hitting the block gas limit and related issues with transaction inclusion.
Core Functionality
The deployer coordinator allows the factory to complete the process of deploying a Hyperdrive instance at a specified deployment ID with the deploy
function or deploy the components of a Hyperdrive instance at a specified deployment ID with the deployTarget
function.
Related Contracts
contracts/src/interfaces/IHyperdriveDeployerCoordinator.sol
contracts/src/deployers/HyperdriveDeployerCoordinator.sol
contracts/src/deployers/erc4626/ERC4626HyperdriveDeployerCoordinator.sol
contracts/src/deployers/steth/StETHHyperdriveDeployerCoordinator.sol
Deployers
Hyperdrive deployers are contracts that are responsible for deploying the components of a Hyperdrive instance. The only reason for these deployers to exist is to hold the bytecode that they are responsible for deploying and provide access to these deployments to deployer coordinators that consume their service. If the code size limit and block gas limit were larger, the deployer coordinator could deploy the components of Hyperdrive itself.
Core Functionality
The bytecode contained by a deployer can be deployed using the deploy
function.
Related Contracts
contracts/src/interfaces/IHyperdriveCoreDeployer.sol
contracts/src/interfaces/IHyperdriveTargetDeployer.sol
contracts/src/deployers/erc4626/ERC4626HyperdriveCoreDeployer.sol
contracts/src/deployers/erc4626/ERC4626Target0Deployer.sol
contracts/src/deployers/erc4626/ERC4626Target1Deployer.sol
contracts/src/deployers/erc4626/ERC4626Target2Deployer.sol
contracts/src/deployers/erc4626/ERC4626Target3Deployer.sol
contracts/src/deployers/erc4626/ERC4626Target4Deployer.sol
contracts/src/deployers/steth/StETHHyperdriveCoreDeployer.sol
contracts/src/deployers/steth/StETHTarget0Deployer.sol
contracts/src/deployers/steth/StETHTarget1Deployer.sol
contracts/src/deployers/steth/StETHTarget2Deployer.sol
contracts/src/deployers/steth/StETHTarget3Deployer.sol
contracts/src/deployers/steth/StETHTarget4Deployer.sol
Proxies
Hyperdrive proxies are the entrypoints into Hyperdrive pools. The code size limit prevents Hyperdrive from being deployed in a single self-contained contract. To avoid this issue, Hyperdrive deployments are structured as a proxy that delegates its storage to a set of logic contracts (called "targets") via the standard delegatecall
pattern. For read-only calls, the proxy uses a force-revert delegatecall pattern that delegates its storage to a logic contract (the target0 logic contract by convention) and ensures that the call reverts for added security. The logic contracts are immutable and can never be changed. All of the logic contracts share the same storage layout, so the proxy system behaves like a single large smart contract.
Core Functionality
The proxy is the entrypoint to Hyperdrive, and with this in mind, it exposes all of the following core Hyperdrive functions:
initialize
openLong
closeLong
openShort
closeShort
addLiquidity
removeLiquidity
redeemWithdrawalShares
checkpoint
Related Contracts
contracts/src/interfaces/IHyperdrive.sol
:contracts/src/interfaces/IERC4626Hyperdrive.sol
:contracts/src/interfaces/IStETHHyperdrive.sol
:contracts/src/external/Hyperdrive.sol
:contracts/src/instances/erc4626/ERC4626Hyperdrive.sol
:contracts/src/instances/steth/StETHHyperdrive.sol
:
Targets
Hyperdrive targets are the logic contracts that shard Hyperdrive's bytecode over several addresses to avoid code size limitations. To avoid making several costly external calls every time a Hyperdrive function is invoked, Hyperdrive targets are completely self-contained and contain all of the required bytecode for the functions that they expose.
Core Functionality
Each of the Hyperdrive targets exposes one or more of Hyperdrive's core functions:
initialize
openLong
closeLong
openShort
closeShort
addLiquidity
removeLiquidity
redeemWithdrawalShares
checkpoint
By convention, all of the getters are contained in HyperdriveTarget0
, so all of the other target contracts contain only stateful functions.
Related Contracts
contracts/src/external/HyperdriveTarget0.sol
contracts/src/external/HyperdriveTarget1.sol
contracts/src/external/HyperdriveTarget2.sol
contracts/src/external/HyperdriveTarget3.sol
contracts/src/external/HyperdriveTarget4.sol
contracts/src/instances/erc4626/ERC4626Target0.sol
contracts/src/instances/erc4626/ERC4626Target1.sol
contracts/src/instances/erc4626/ERC4626Target2.sol
contracts/src/instances/erc4626/ERC4626Target3.sol
contracts/src/instances/erc4626/ERC4626Target4.sol
contracts/src/instances/steth/StETHTarget0.sol
contracts/src/instances/steth/StETHTarget1.sol
contracts/src/instances/steth/StETHTarget2.sol
contracts/src/instances/steth/StETHTarget3.sol
contracts/src/instances/steth/StETHTarget4.sol
Last updated