This is a developer level guide to the Sai source layout and how the different objects relate to each other.
Sai is Simple-Dai, a simplification of the Dai Stablecoin System intended for field testing and refining Dai components. Sai has several features that distinguish it from Dai:
- trusted price feed
- single collateral type
- global settlement
- liquidations at fixed price (rather than auctions)
This document is an introduction to Sai, aimed at those seeking an understanding of the Solidity implementation. We assume knowledge of the white paper, a high level overview of Dai. A reading of the purple paper, the (in progress) detailed Dai technical specification and reference implementation, is strongly encouraged but not required.
Sai uses the following tokens:
gem
: underlying collateral (wrapped ether, in practice)skr
: abstracted collateral claimsai
: stablecoinsin
: anticoin, created when the system takes on debt
Sai has the following core components:
vox
: target price feedtub
: CDP record storetap
: liquidation mechanismtop
: global settlement facilitator
Sai is configured by the following 'risk parameters':
way
: Sai reference price driftcap
: Debt ceilingmat
: Liquidation ratiotax
: Stability feeaxe
: Liquidation penaltygap
: Join/Exit and Boom/Bust spread
skr
is a token wrapper.
join
: depositgem
in return forskr
exit
: claimgem
with theirskr
.
skr
is a simple proportional claim on a collateral pool, with the
initial gem
<->skr
exchange ratio being 1:1. The essential reason
for this abstraction will be developed later, but for now it is
sufficient to see skr
as a token with intrinsic value.
The gem
/skr
exchange rate is called per
, and is calculated as the
total number of deposited gem
divided by the total supply of SKR.
The reference price of gem
(in practice, ETHUSD) is provided by the
pip
, an external oracle. The pip
is completely trusted.
The reference price of skr
is then given by the dynamic tag
, e.g.
the price of SKR in USD.
The vox
provides the Sai target price, given in terms of the
reference unit, by par
. For example, par == 2
with USD as the
reference unit implies a target price of 2 USD per Sai.
The target price can vary in time, at a rate given by way
, which is
the multiplicative rate of change per second.
The vox
is the same as that in Dai, but with the sensitivity, how
,
set to zero. Adjustments to the target price are made by adjusting the
rate of change, way
, directly with coax
. In future Sai iterations,
how
may be non-zero and way
adjustments will then follow
automatically via the feedback mechanism. The vox
component is subject
to ongoing economic modelling research.
The tub
is the CDP record system. An individual CDP is called a cup
(i.e. a small container), and has:
lad
: an ownerink
: locked SKR collateralart
: debt
It is crucial to know whether a CDP is well collateralised or not:
safe(cup)
returns a boolean indicating this.
safe
aggregates price information from the vox
and the tub
and
compares the reference value of a CDPs debt and collateral.
The following tub
acts are not possible if they would transition a CDP
to unsafe:
open
: create a new CDPgive
: transfer ownership (changeslad
)
lock
: deposit SKR collateral (increasesink
)free
: withdraw SKR collateral (decreasesink
)
draw
: create Sai (increasesart
,rum
)wipe
: return Sai (decreasesart
,rum
)
shut
: clear all CDP debt, unlock all collateral, and delete the record
bite
: liquidate CDP (zerosart
, decreasesink
, mintssin
totap
)
Unsafe CDPs need to be liquidated. When a cup
is not safe
, anyone
can perform bite(cup)
, which takes on all CDP debt and confiscates
sufficient collateral to cover this, plus a buffer.
This returns the CDP to a safe state (possibly with zero collateral).
There are other possible implementations of bite
, e.g. only taking
sufficient collateral to just transition the CDP to safe, but the
described implementation is chosen for simplicity.
bite
mints the sin
associated with the CDP to the tap
- the
liquidator.
The tap
is a liquidator. It has three token balances that determine
its allowed behaviour:
joy
: Sai balance, surplus transferred fromdrip
woe
: Sin balance, bad debt transferred frombite
fog
: SKR balance, collateral pending liquidation
and one derived price, s2s
, which is the price of SKR in Sai. The
tap
seeks to minimise all of its token balances. Recall that Sai can
be canceled out with Sin via heal
.
The tap
has two acts:
boom
: sell Sai in return for SKR (decreasesjoy
andwoe
, decreases SKR supply)bust
: sell SKR in return for Sai (decreasesfog
, increasesjoy
andwoe
, can increase SKR supply)
boom
is the simpler function and can be thought of as buy and burn.
Given a net Sai balance, sell the Sai in return for SKR, which is
burned.
bust
is really two functions in one: collateral sell off (aka flip
),
and inflate and sell (aka flop
). When fog
is non zero it is sold in
return for Sai, which is used to cancel out the bad debt, woe
. If
fog
is zero but the tap
has a net Sin balance, then SKR is minted
and sold in return for Sai, up to the point that the net Sin balance is
zero.
Through boom
and bust
we close the feedback loop on the price of
SKR. When there is surplus Sai, SKR is burned, decreasing the SKR supply
and increasing per
, giving SKR holders more GEM per SKR. When there is
surplus Woe, SKR is inflated, increasing the SKR supply and decreasing
per
, giving SKR holders less GEM per SKR.
The reason for wrapping GEM in SKR is now apparent: it provides a way to socialise losses and gains incurred in the operation of the system.
Two features of this mechanism:
-
Whilst SKR can be inflated significantly, there is a finite limit on the amount of bad debt the system can absorb - given by the value of the underlying GEM collateral.
-
There is a negative feedback between
bust
andbite
: as SKR is inflated it becomes less valuable, reducing the safety level of CDPs. Some CDPs will become unsafe and be vulnerable to liquidation, creating more bad debt. In an active market, CDP holders will have to be vigilant about the potential for SKR inflation if they are holding tightly collateralised CDPs.
A key feature of Sai is the possibility of cage
: shutting down the
system and reimbursing Sai holders. This is provided for easy upgrades
between Sai iterations, and for security in case of implementation flaws
- both in the code and in the design.
An admin can use the top
to cage
the system at a specific price (sai
per gem), or by reading the last price from the price feed.
First, sufficient real gem
collateral is taken such that Sai holders
can redeem their Sai at face value. The gem
is moved from the tub
to
the tap
and the tap.cash
function is unlocked for Sai holders to
call.
Any remaining gem
remains in the tub
. SKR holders can now exit
.
CDP holders must first bite
their CDPs (although anyone can do this)
and then free
their SKR.
Some important features of cage
:
- Sai holders are not guaranteed their face value, only preferential payout.
- the full real collateral pool is tapped to make Sai whole. SKR is a risk-bearing token.
- SKR holders will receive a poor rate if they try to
exit
before all CDPs are processed bybite
. To prevent accidental earlyexit
,top.flow
is provided, which will only enableexit
after all CDPs are processed, or a timeout has expired.
The top
also serves as a useful frontend entrypoint to the system, as it
links to all other components.
In a simpler system with no interest rates, we could denominate CDP debt,
the tab
, directly in sin
. However with non zero interest, tab
is a
dynamic quantity, computed from art
, a rate-normalised per-CDP debt unit,
and chi
, the product of accumulated rates that converts art
into a real
debt amount. rum
is the total art
across all CDPs, and can be used
to determine the total debt backed by CDPs, din
.
tab(cdp) = cdp.art * chi
The internal debt price, chi
, is dynamic and is updated by the drip
act, which also collects unprocessed revenue.
The chi
abstraction allows us to compute the per CDP debt, and the
total unprocessed revenue, with varying tax
, in constant time.
This version of Sai (aka Dai v1) is collectively governed by the holders of
a token, gov
. The specifics of the governance mechanism are
out of scope for this document. The gov
token is also used to pay usage
fees: the fee
is similar to the tax
, and causes the rhi
accumulator to
increase relative to chi
. The difference between rhi
and chi
can be
used to determine the total outstanding fee, the rap
. Fees are paid on
wipe
, and the amount payable is scaled with the amount wiped.
Fees are paid in gov
, but the outstanding fee is denominated in Sai.
Therefore we need a price feed for gov
: this is the pep
. The mechanism
in wipe
is meant to be robust against failure of the pep
feed.
Importantly, unpaid fees are not used to determine a CDPs safety (this may change in a future release).
Sai is designed with two authorities, dad
and chief
.
-
dad
is a DSGuard, and is used for internal contract-contract permissions, allowing e.g. thetub
tomint
andburn
Sai.dad
is the authority of thetub
andtap
, and alsosai
,sin
andskr
. -
chief
restricts access totop
andmom
, which are the admin interfaces to the system.chief
is intended to be a DSRoles instance, but any authority implementation could be used.
Sai is a complex multi-contract system and has a slightly involved deployment process. The prerequisities to the deployment are:
pip
, a collateral price feedpep
, a governance price feedgem
, a collateral tokenpit
, a token burnerchief
, the external authority
For testing purposes, bin/deploy
will create the prerequisites for you
if you don't supply them.
In addition, Sai utilises on-chain deployers, called fabs, for creating
fresh basic components on chain. These are defined in fab.sol
.
The main contract deployment is defined in DaiFab
, and requires
multiple calls because of the size of the contracts.
The full contracts can be deployed to e.g. ethlive with the following,
after which the contract addresses will be saved in load-env-ethlive
.
bin/deploy-fab
. load-fab-ethlive
bin/deploy
per
: gem per skrpar
: ref per saitag
: ref per skrpip
: ref per gemfix
: gem per sai aftercage
fit
: ref per skr aftercage
-
pip
: trading pips -
cup
: small container for CDP info -
tub
: larger container for cups -
tap
: liquidity provider -
top
: top-level system manager -
way
: which way the target price is heading -
cap
: upper limit of Sai issuance -
mat
: lower limit of collateralisation -
tax
: continually paid by CDP holders -
axe
: penalty applied to bad CDP holders -
gap
: gap between buy and sell -
pie
: Real collateral that SKR holders share -
air
: Abstracted Collateral backing CDPs -
ice
: Debt that is locked up with CDPs -
fog
: Murky liquidatedair
that we want to get rid of -
joy
: SKR holders are happy about this Sai surplus -
woe
: SKR holders are sad about this Sin debt