External Positions
An "external position" is a type of fund holding introduced in v4 that:
is not a fungible ERC20 token
exists outside of the vault as a distinct contract (one per external position instance)
reports its value to the fund in terms of its underlying holdings and liabilities
cannot have value withdrawn during a shares redemption (investors in funds that use external positions should almost never redeem in-kind, as any value inside of external positions will effectively be forfeited)
is a "beacon" proxy contract that uses the library dictated by the fund's current release (e.g., Sulu)
External Position Types
Each external position is associated with a "type" that is written to ExternalPositionProxy.EXTERNAL_POSITION_TYPE upon its deployment. This type (e.g., a Compound debt position) instructs the system as to which library and parser contracts to use with proxy interactions.
A vault can have many active external positions of the same type.
There are no globally-enforced limitations on the asset counts that can be managed within any external position.
Persistent architecture
An ExternalPositionProxy is deployed by a persistent ExternalPositionFactory , which serves as an enduring registry of external position "types" (e.g., Compound CDP) and all valid ExternalPositionProxy instances (i.e., those created via the factory).
The ExternalPositionProxy is deployed with a VaultProxy as its owner.
Upon each call, ExternalPositionProxy fetches its library via a getExternalPositionType() callback to its VaultProxy.
Protected / trusted calls to state-changing actions in the ExternalPositionProxy should pass through a protected receiveCallFromVault() , guaranteeing the call passed through the owning VaultProxy .
Release architecture
The lifecycle of an external position is managed via ExternalPositionManagerActions on the ExternalPositionManager extension:
CreateExternalPosition-- create (deploy) a new external position and activate it on theVaultProxyCallOnExternalPosition-- make allowed arbitrary calls to interact with the external position, and transfer assets to / from theVaultProxyRemoveExternalPosition-- deactivate an external position from theVaultProxyReactivateExternalPosition-- reactivate an existing external position on theVaultProxy
Each of these actions has its own policy hook, to allow granular control of risk management.
The ExternalPositionManager stores two updatable reference contracts per external position type, which contain all logic specific to that type:
libis the target library of the beaconExternalPositionProxy, and contains the business logic for its local accounting and interactions with external protocolsparseris a contract used by theExternalPositionManagerto validate and parse call data for each specific action on its external position type
For example, VaultA has a Compound CDP external position already deployed. To add collateral to the CDP:
an asset manager calls the
ExternalPositionManager'sCallOnExternalPositionaction viaComptrollerProxy.callOnExtension()with the desired payload to add 100 cDAI as collateralthe
ExternalPositionManagerlooks up its storedCompoundDebtPositionParserand forwards it the payloadthe
CompoundDebtPositionParservalidates the call, e.g., that cDAI is a valid cTokenthe
CompoundDebtPositionParserformats the outgoing 100 cDAI intoassetsToTransferandamountsToTransferarrays, which it returns to theExternalPositionManagerthe
ExternalPositionManagerpasses the payload along with the data for assets to transfer (100 cDAI) and to receive (none) to theVaultProxythe
VaultProxytransfers 100 cDAI to the targetExternalPositionProxythe
VaultProxycallsExternalPositionProxy.receiveCallFromVault(), passing in the payloadExternalPositionProxycalls back to theVaultProxyfor the library to use for its type (Compound CDP), which it pulls from theExternalPositionManagerthe
ExternalPositionProxyuses the returnedCompoundDebtPositionLibto parse and execute theAddCollateralAssetsaction, adding cDAI to its internal accounting of its managed assets and interacting with Compound to use cDAI as collateral as needed.
Last updated
Was this helpful?