Extensions and Plugins

Though all contracts for this release are fully audited and trusted, we would like to allow for third party development of plugins (sooner) and extensions (later) in upcoming releases.

For that reason, the release-level contracts are architected like a trust onion, with each layer outward being less trusted:

  • core (e.g., Comptroller contracts, Vault contracts, fund deployment)

  • extensions (e.g., IntegrationManager)

  • plugins (e.g., integration adapters like KyberAdapter)

The core dictates the actions that each extension can take on VaultProxy state. E.g., in this release, no VaultProxy state-changing actions are allowed by the PolicyManager, whereas IntegrationManager and FeeManager are allowed limited sets of actions.

Additionally, any state-changing call to the VaultProxy must both originate from and return through the same ComptrollerProxy of the corresponding fund, guaranteeing that extensions can only act upon a particular VaultProxy when called by the fund itself.

Extensions can then define their own rules for local behavior, e.g., how its plugins work (plugins are defined and used by all current extensions, but are not essential to an extension). For the official extensions provided by the core protocol, plugins are designed NOT to have direct state-changing authority on core contracts or extensions, and all operate in their own context (i.e., they are not delegate-called).

E.g., IntegrationManager and an adapter

The IntegrationManager is an extension that defines rules for how "adapters" (its plugins) can use a fund's assets in interactions with external DeFi protocols. The IntegrationManager itself has access to state-changing functions on the VaultProxy related to spending and accounting for asset holdings. It provisions these holdings to its adapters as instructed by the user input in callOnIntegration(). The rough pathway is as follows:

  • permissioned user calls IntegrationManager.__callOnIntegration() via ComptrollerProxy.callOnExtension() with instructions to use AdapterA, SelectorB, and CalldataC

  • IntegrationManager calls to AdapterA and asks for the assets and max amounts to be spent and the assets and min amounts to be received in the tx, along with how the assets to be spent should be provisioned to the adapter (e.g. approval or transferal)

  • the IntegrationManager provisions the spend assets to the adapter as instructed

  • the adapter uses the spend assets however it sees fit, generally in exchange for other assets, and then returns all unused spend asset balances and all incoming asset balances to the VaultProxy

  • the IntegrationManager then runs validation on the amounts spent and received, and provides all final incoming and outgoing asset balances to the PolicyManager for further validation

One nuance that may become important (and changed) in an upcoming release is that the adapter (rather than the IntegrationManager) is responsible for parsing the assets to be spent and received from the user-input calldata, which has the potential for malicious abuse.