# Smart Contracts
Divider is the accounting engine of the Sense Protocol. It allows users to "divide"
Target assets into ERC20 Principal Tokens (PTs) (opens new window) & Yield Tokens (YTs) (opens new window) with the help of numerous auxiliary contracts including
Adapter Factories, and the
Periphery contract. Each Target can have an arbitrary number of active instances or
series of PTs and YTs, and each series is uniquely identified by their
maturity. The Divider reads
scale values (opens new window) from Adapters to determine how much Target to distribute to PT & YT holders at or before maturity. Constituting the "core" of Sense, these contracts fully implement the Sense Lifecycle (opens new window) as well as permissionless series management & onboarding of arbitrary Adapters.
The core is accompanied by the following modules:
Space, a PT/Target AMM Pool (opens new window) that offers an LP position that is principal protected, yield-generating, and impermanent loss (IL) minimized
All user journeys & entry points of the Sense Protocol are outlined here (opens new window), and the following sections dive into each contract.
The Divider contains the logic to
issue() ERC20 PTs and YTs, re-
combine() those assets into Target before their maturity,
collect() Target with YTs, and
redeem() at or after maturity. Beyond series management, such as initialization & settlement, the Divider purposefully pushes application logic to the Adapters. Divider math derivations (opens new window) (thank you ABDK!).
Following a hub and spoke model, Adapters surround the Divider and hold logic related to their particular application (opens new window), such as stripping yield from yield-bearing assets. Once an Adapter is onboarded, users can initialize/settle series, issue PTs/YTs, and collect/redeem their Target via the Divider.
The Adapter holds the Target before a series' maturity and contains logic to handle arbitrary airdrops from native or 3rd party liquidity mining programs. Typically denominated in another asset, airdropped tokens are distributed to YT holders in addition to the yield accrued from the Target. Moreover, Adapters store parameters related to their individual applications, which is digested by the Divider when performing the above-mentioned operations. The parameters include:
target- address to the Target
underlying- address to the Target’s underlying
oracle- address to the Oracle of the Target's Underlying
stake- token to stake at issuance
stakeSize- amount to stake at issuance
minm- min maturity (seconds after block.timestamp)
maxm- max maturity (seconds after block.timestamp)
mode- maturity date type (0 for monthly, 1 for weekly)
ifee- series issuance fee (opens new window)
tilt- any principal set aside for YTs at maturity (relevant for non-stripping applications)
level- feature access codes
Non-airdrop Adapter implementations must inherit
BaseAdapter and override the following functions:
The other overridable functions are mostly available for non-stripping adapters that require additional flexibility, such as
BaseAdapter.onRedeem(), a hook called on PT redemptions.
Airdrop adapter implementations must inherit
CropAdapter and override all required functions mentioned above as well as
_claimReward(), which allows the adapter to harvest airdrops from the Target and distribute them to YT holders.
On collects and redemptions, the Divider queries the adapter for scales, an abstract metric used to define how the Target is divided between PT and YT holders.
How the scale is determined, or even what the scale represents, is dependent on the adapter’s application. For example, in the yield stripping application, scale represents the exchange rate between the Target & Underlying, and the scale’s growth is the yield earned on the Target.
However, because the scale calculation is abstracted away from the Divider, the adapter has full discretion in how and when it determines the scale value.
There are two types of Adapters:
- Verified Adapters - verified by the Sense team and can be permissionlessly deployed by Adapter Factories
- Unverified Adapters - unverified or deemed unsafe by the Sense team and could be controlled by malicious actors
During Sense’s guarded launch (opens new window), the Divider interfaces only with Verified Adapters. However, once the
permissionless flag is enabled, users can permissionessly onboard Adapters via
Divider.addAdapter() and leverage Sense's infrastructure to build new fixed-income products, structured products, and yield primitives never before seen in DeFi.
# Adapter factory
The Adapter factory allows any person to deploy a Verified Adapter for a given Target in a permissionless manner.
Following a gradual expansion, Sense Finance will deploy one Adapter Factory for each protocol (e.g cTokens Adapter Factory, Curve LP Share Adapter Factory, etc).
Most factories are be similar except for how they implement
_exists(), a method that checks whether the Target address supplied is a supported asset of that protocol.
To create an Adapter Factory, the contract needs to inherit from
BaseFactory and override
Once the Adapter Factory is built and verified in the Periphery, anyone can deploy a Verified Adapter via
For Series Actors, the Periphery exposes the public entry points to deploy Verified Adapters and initialize series. The Target Sponsor calls
deployAdapter which deploys an Adapter via an Adapter Factory. The Series Sponsor calls
sponsorSeries to initialize a series in the Divider and deploy a Space pool.
Series sponsorship of all Adapters is initiated through the Periphery.
Space only holds PTs & Targets, so users need to execute additional steps to
combine() in order to enter/exit into/from a YT position (opens new window). The Periphery allows users to bundle the necessary calls behind a single function interface and perform the following operations atomically, flash loaning Target from an Adapter when need be:
Similarly, the Periphery exposes several atomic transactions for LP management through Space.
Sense Protocol uses Rari's ERC20 implementation (opens new window) and defines:
Tokenas a minimalist ERC20 implementation with auth'd
mint(). Used for PTs.
YTas a minimalist yield token implementation that:
- inherits from
Divider.collect()) and overrides
transferFrom()to also call
- inherits from
Space is a PT/Target AMM Pool built on Balancer V2. It implements the Yieldspace (opens new window) invariant but introduces a meaningful improvement by allowing LPs to deposit a yield-generating quote asset, i.e. the Target, instead of the PT’s Underlying, as was originally conceived.
Building on the shoulders of giants, Space exposes a manipulation-resistant LP share price and a TWAR (time-weighted average rate). Each Series has a unique
Space for PT/Target trading, which is deployed through the
Trust to provide access control via
requiresTrust to contracts inheriting from it. In some contracts, we introduce per-function access control for greater granularity, such as
Admin docs are located in the security page. (opens new window)