The Rico Credit System (RCS) in its end state issues a stable-value, credibly neutral debt unit called a stability primitive.
Rico Credit System 0 (RCS0) shows some important steps toward an ossified stability primitive. See principles for a discussion of some high-level guiding principles.
Key features that might be new to some are hook, log-scale tick, single-step, and feed.
Rico emphasizes minimalism. This makes it easier to audit and to understand the entire system at once. Everyone using the system should understand all the components and how they fit together. Also, in our experience it speeds up research and development, as the more you delete the less you have to refactor when adding new features.
There are three core components:
vat
is the main CDP accounting module
vox
is the par price adjustment mechanism
vow
is the total system profit/loss balancing mechanism
And two auxiliary components, defined by interface:
feed
subsystem puts price feeds from oracle systems, AMMs, and other source, into one common base protocol
hook
subsystem is called by vat to lock, free, and appraise collateral
There are two tokens:
Vat
is the main CDP accounting module. It holds collateral tokens and mints/burns rico.
The vat
module can:
frob
a CDP to adjust collateral balance and debt
bail
a CDP to auction off collateral to cover an underwater position
safe
to determine if a CDP is safe, risky, or unknown
drip
accumulated interest
flash
to flash mint rico
The vat calls out to the hook
subsystem to determine if a CDP is safe. The hook
calls out to feed
to get price data.
Rico approve is generally unnecessary, as vat
and hook
use Gem mint and burn instead of transferFrom.
Vow
balances system surplus and deficit. It provides an extra backstop for bad debt with mint-and-sell (flop
), which is offset by the buy-and-burn from interest charged (flap
).
There are three big conceptual differences from equivalent mechanics in previous systems.
vow
does not handle collateral auctions
RISK is the buy/burn and mint/sell token. On flop
, vow
mints and sells RISK for Rico. On flap
, vow
auctions off surplus Rico for RISK, which is burned.
Rico and RISK approve is generally unnecessary, as vow
uses Gem mint and burn instead of transferFrom.
The vow
module can:
keep
to cancel out deficit with surplus, and fill a buy/burn or mint/sell auction if applicable
Rico development focuses on eventual ossification. See principles for why this is important. To ossify, Rico must have incentive structures that hold up under adverse market conditions. It’s not sufficient to pay janitors a set fee to kick off a standing auction, as under congestion the fee might not be sufficient.
A Rico auction starts when the necessary conditions are met and a taker finds it profitable to fill. The taker’s reward is a discount computed based on the system’s need to fill the auction. Saving some details, the discount is proportional to:
Effectively, the system acts as a simple agent that considers its own risk when pricing the asset. This allows for a simpler auction mechanism that acts more rationally without needing a backdoor.
Vox
is the par price adjustment mechanism.
The par price is the system’s internal definition of the price of the synthetic in terms of some external reference asset. Since there’s no global settlement, some might find it easier to understand par
as a global multiplier used to calculate collateral requirements.
The rate of change of par
, called way
, is the primary monetary lever of the system used to balance supply and demand. It’s adjusted automatically when Rico’s market price in terms of REF, the external reference asset, deviates from par
.
Changes in this price rate adjust the present value of the asset in the same way that changes in the interest rate on a variable rate bond adjusts its present value.
This is in contrast to using the quantity rate or fee
, which is a per-collateral-type risk parameter which should be understood more like an insurance fee.
The main advantage of this model is that price rate be negative (way < 1
), which gives the system the ability to deal with “squeezes” or “hoarding” without the problem of the quantity rate zero bound, the inability of the bank to charge a negative quantity rate in a sustainable manner. In other words, the system can make the effective rate of borrowing vs the external reference asset negative while still maintaining positive cashflow for the system.
Vox
calls the feed
subsystem to find the market price of rico in terms of REF, adjusts way
depending on the difference between the market price and par
, and prorates par
according to way
.
The vox
module can:
poke
to update par
and way
Rico vox
uses a capped log-scale tick controller
. Many might be used to earlier target rate feedback mechanisms which used linear-scale PI or PID controllers.
A tick controller
is an integral controller
. An integral controller doesn’t have a proportional term. This means the price rate does not generally change based on short-term market conditions, instead changing based on prolonged differences between market price and par price.
A tick controller “ticks” up or down a constant amount in response to stimuli. On poke
, Rico vox
raises or lowers the price rate by a constant sensitivity parameter, accumulated over the time between pokes.
Rico vox
is log-scale because its sensitivity parameter is a multiplier, not an addend. This means that vox
could be thought of as controlling the log of the price rate on linear scale, or the price rate on log scale. vox
is log-scale instead of linear so that controller corrections more accurately line up with market behavior; for example, arbitrageurs care more about a par change from 1 to 2 than a change from 100 to 101.
Rico vox
clamps the price rate to minimum and maximum values to prevent excessive windup.
vox
roughly multiplies the price rate by the sensitivity each second par exceeds market price (denominated in REF), and divides the price rate by the sensitivity each second market price exceeds par.
vat
is collateral-agnostic. For example, it’s not generally sufficient to encode ink
as a single uint
, or to pair a collateral type with a single uint
price feed. Rico separates these and other collateral-specific design decisions into hook
. vat
only includes operations that are relevant to all collateral types. For any new collateral type, if there’s no existing hook
, the programmer can write a new hook
.
hook
contains collateral-specific integrations. Each collateral type has a hook, and some collateral types can use the same hook. For example, an ERC20 hook would lock up or free collateral tokens on frob
and send them to the keeper on bail
.
hook
implements:
frobhook
: called on frob to lock/free collateral
bailhook
: called on bail to auction off collateral to pay down urn’s debt
safehook
: called on safe to appraise collateral in terms of REF
ink
: called on Vat.ink to read an urn’s collateral information
In previous (pre-hook) systems, the vat
was carefully designed to perform all logic without external calls. This rule adds unnecessary complexity that fails to fully address the issues created by such dependencies, so it’s relaxed in Rico hook
. frob
and bail
both have reentrancy locks.
Feed
is the subsystem responsible for providing price feeds.
Feedbase
is a generic object that serves as a point of coordination that makes it easier to compose various receivers, adapters, and combinators.
A receiver is a contract that verifies the signature on a signed message obtained off-chain. This is how market prices from spot exchanges should be read – the oracle is the data source.
An adapter is a contract that simply copies data from an existing on-chain feed into Feedbase.
A combinator is a contract that combines data.
Feeds can be either read or written depending on the source implementation. Each feed is defined by a (src, tag) pair, where src
is the oracle address and tag
is the feed ID. When pulling feed data, Feedbase will either call read
to compute a fresh oracle output, or fetch a previously written output. It’s up to the developer which is best. RCS0 feeds all call read
, but if this changes, keepers will call feed.poke
before frob
and vox.poke
so that pull
fetches recent data.
Feedbase is a labor of love that doesn’t define any incentive. Such design decisions are left to the caller.