The system design document in our Github repository provides an overview of the smart contracts architecture and details about the protocol implementation. See the developer documentation for technical details on the smart-contract interfaces and functionalities
The Protocol Operations chapter explains how these contracts work together to provide the core functionality of the protocol.
Many Reserve Protocol smart contracts rely on the proxy pattern, whereby users interact with proxy contracts which store data but which do not contain business logic. Rather, all function calls in these proxy contracts are delegated to implementation contracts to execute the desired logic. Implementation contracts for the most recent version of the protocol are provided below.
Mainnet Addresses (v3.0.1)
Base Addresses (v3.0.1)
Some Monetary Units
Reserve Protocol refers to units of financial value in a handful of different ways, and treats them as different dimensions. Some of these distinctions may seem like splitting hairs if you're just thinking about one or two example RTokens, but the differences are crucial to understanding how the protocol works in a wide variety of different settings.
The following are the three main financial units that apply to the protocol:
Unit of Account: any particular RToken must have a single Unit of Account. This unit is used internally to compare the values of different assets, as when deciding when there's enough revenue to start an auction, or in which of several surplus assets we hold the largest surplus.
By default, the unit of account for all RTokens is USD. As this financial unit is mostly for internal calculations (such as converting price feeds), there is no reason for an RToken deployer to change it—it is therefore also not an RToken parameter.
Target unit: each collateral token in an RToken basket is expected to generally be stable or appreciating against some exogenous currency. The exogenous currency is that collateral's target unit. We expect that in many RTokens that people actually want, all of those target units will be the same, and we can speak of the RToken maintaining stability or appreciation against its target unit.
Reference unit: when collateral tokens are expected to appreciate, it's generally because some DeFi protocol produces a “receipt token” that is freely redeemable for some base token, the redemption rate of which is expected to monotonically increase over time. That base token is the reference unit for the collateral token.
A couple examples:
- For a Compound collateral token such as cUSDC, the unit of account is USD, the reference unit USDC and target unit USD.
- For an Aave collateral token such as aUSDP, the unit of account is USD, the reference token USDP and target unit USD.
- Let's say we're building a pure-stable USD basket, out of USDC, USDP, and DAI. The unit of account would surely be USD. Each collateral token would also be its own reference unit, and their target units would be USD.
Reserve Protocol expects collateral tokens (e.g. cUSDC) to be in a known, predictable relationship with the reference units (e.g. USDC), and the reference units to be in a known, predictable relationship with the target units (e.g. USD) and will flag the collateral token as defaulting if any of these relationships appear to be broken.
“Baskets” in the Reserve Protocol are arrays of financial values that the protocol references when keeping RTokens fully collateralized at all times. We differentiate between the following three types of baskets:
Prime basket: This is the target collateral basket at the onset of an RToken that defines which collateral needs to be deposited for issuances. The prime basket is directly set by governance, and only changes through successful governance proposals. It consists of an array of triples (
<collateral token, target unit, target amount>) where each portion of the basket has a
target amountof the
target unitthat should be represented by
For example, if the prime basket contains the triple
<cUSDC, USD, 0.33>, that means "The RToken should contain 0.33 USD per basket, as represented by cUSDC".
Reference basket: When the prime basket is updated by governance or in the case of a collateral default, the protocol will determine a new “Reference Basket” and then take certain actions (described in the Protocol Operations section) to change the collateral makeup until it matches the new basket. This new basket is called the reference basket and, like the prime basket, consists of a set of triples
<collateral token, reference unit, reference amount>. Each triple means that each basket unit must contain an amount of
collateral tokencurrently equivalent to
reference amountof the
For example, if the reference basket contains the triple
<aDAI, DAI, 0.33>, then one basket unit should contain whatever amount of aDAI is redeemable in its protocol for 0.33 DAI.
Collateral basket: the collateral basket is derived, moment-by-moment and on-demand, from the reference basket. Since DeFi redemption rates can change every transaction, so can the collateral basket. The collateral basket is a set of pairs
<collateral token, token amount>. Each pair means that each basket unit must contain
For example, if the reference basket contains the pair
<cUSDC, O.29>, then one basket unit will contain 0.29 cUSDC.
System States and Roles
Reserve Protocol contains five core governance roles that any governance smart contract can easily integrate in order to create new governance systems for RTokens:
OWNER: the top level decision maker, typically a decentralized governance smart contract, responsible for setting or updating all RToken parameter values, RToken baskets, etc. - The RToken OWNER has the power to:
- grant and revoke roles to any Ethereum account
- set governance parameters
- upgrade system contracts
PAUSER: has the ability to pause and unpause an RToken’s system. The PAUSER role should be assigned to an address that is able to act quickly in response to off-chain events, such as a Chainlink feed failing. It is ok to have multiple pausers. It can be robot-controlled. It can also consist of a 1-of-N multisig for high availability and coverage. It is acceptable for there to be false positives, since redemption remains enabled. See the table below for more information on what exactly a “pause” of an RToken means.
SHORT_FREEZER: has the ability to freeze an RToken’s system for a short period of time. The SHORT_FREEZER role should be assigned to an address that might reasonably be expected to be the first to detect a bug in the code and can act quickly, and with some tolerance for false positives, though less than in pausing. It is acceptable to have multiple short freezers. It can be robot-controlled. It can also consist of a 1-of-N multisig for high availability and coverage. If a bug is detected, a short freeze can be triggered which will automatically expire if it is not renewed by LONG_FREEZER.
When the SHORT_FREEZER call freezeShort(), they relinquish their SHORT_FREEZER role, and can only be re-granted the role by the OWNER (governance). The OWNER may also step in and unfreeze at any time.
LONG_FREEZER: has the ability to freeze an RToken’s system for a long period of time. The LONG_FREEZER role should be assigned to an address that will highly optimize for no false positives. It is much longer than the short freeze. It can act slowly and needs to be trusted. It is probably expected to have only one long-freezer address. It allows only 6x uses per long-freezer. It exists so that in the case of a zero-day exploit, governance can act before the system unfreezes and resumes functioning.
When the LONG_FREEZER calls freezeLong(), they spend a “charge”. A LONG_FREEZER starts with 6 charges, and when they run out of charges they relinquish the LONG_FREEZER role. Only the OWNER can re-grant the role or top up an accounts charges.
GUARDIAN: has the ability to reject proposals even if they pass. Should be assigned to a multisig or EOA that can be trusted to act as a backstop. It is acceptable if it is relatively slow to act. Only one guardian address should be defined.
💡 While Reserve Protocol is a fully open system that allows the integration of any custom governance smart contract for RTokens, the Reserve team has deployed a recommended governance system that will be suggested to RToken deployers. If you’re interested in reading about its details, please refer to the Governor Alexios.
The roles mentioned above each have the ability to put their RToken’s system in specific non fully functional states in the case of an attack, exploit, or bug. These states are:
- Paused: when an RToken’s system is paused, all interactions besides redemption, ERC20 functions, staking of RSR, and rewards payout are disabled. An RToken’s system can be paused by any of the Pauser addresses calling
pause()and resumed by calling
- Frozen: when an RToken’s system is frozen, all interactions besides ERC20 functions and staking of RSR are disabled. An RToken’s system can be short-frozen by any of the SHORT_FREEZER addresses calling
shortfreeze(). This freeze can be extended by any of the LONG_FREEZER addresses calling
longfreeze(), or can be resumed by the SHORT_FREEZER or OWNER addresses by calling
What are RTokens?
RToken is the generic name for a stablecoin that gets created on top of the Reserve Protocol. RTokens are fully asset-backed by any combination of ERC-20 tokens and can be protected against collateral default by Reserve Rights (RSR) staking. Each RToken is governed separately.
Anyone can create an RToken
In a similar way as how anyone can create a new trading pair on Uniswap, anyone can permissionlessly create a new Reserve stablecoin (RToken) by interacting with Reserve Protocol’s smart contracts. The protocol applies a system of factory smart contracts that allows anyone to deploy their own smart contract instance.
Creating an RToken can be done either by interacting directly with the Reserve Protocol’s smart contracts or any user interface that gets built on top of it. The first user interface for these smart contracts will be released by LC Labs, a company connected to the Reserve core team that's helping with protocol development. Besides the creation of RTokens, this user interface will also support exploring usage and stats related to RTokens, RToken minting & redeeming, and RSR staking.
Non-compatible ERC20 assets
The following types of ERC20s are not supported to be used directly in an RToken system. These tokens should be be wrapped into a compatible ERC20 token to be used within the protocol. A concrete example is the use of Static ATokens for Aave V2.
- Rebasing Tokens that return yields by increasing the balances of users
- Tokens that take a "fee" on transfer
- Tokens that do not expose the decimals() in their interface. Decimals should always be between 1 and 18.
- ERC777 tokens which could allow reentrancy attacks
- Tokens with multiple entry points (multiple addresses)
- Tokens with multiple entry points (multiple addresses)
- Tokens that do not adhere to the ERC20 standard in general
Advanced RToken parameters
When deploying an RToken, the deployer has the ability to configure many different advanced parameters. The following list goes into detail about what these parameters do and some of the factors the deployer should keep in mind to set them.
As many of these parameters concern the Protocol Operations, we advise reading through that section of the documentation first—as it will give the deployer the necessary context to fully understand all parameters.
The trading delay defines how many seconds should pass after the basket has been changed before a trade can be opened.
A collateral asset can instantly default if one of the invariants of the underlying DeFi protocol breaks. If that would happen, and we would not apply a trading delay, the protocol would react instantly by opening an auction. This would give only auctionLength seconds for people to bid on the auction, making it very possible for the protocol to lose value due to slippage.
The trading delay parameter may only be needed in the early days - before we get to a point where there is a robust market of MEV searchers. We expect that this parameter can be set to zero later on (once a robust market of MEV searchers is established).
The Reserve Protocol includes a generic trading system which can be integrated with any type of trading mechanism, but will only have an implementation for Gnosis EasyAuctions at-launch.
The auction length determines how long auctions stay open for. The situations to keep in mind when determining this value are:
- If it is set too low, back-to-back auctions may not give arbitrageurs enough time to complete arbitrage loops that involve centralized exchanges. We don’t want capital-constrained traders to have to sit out every-other auction.
- If it is set too high, fewer auctions will fill and the protocol will take more time holding the asset being sold. This is because the price can swing more than maximum trade slippage in the unfavorable direction.
Backing buffer (%)
As collateral tokens appreciate, RTokens can be minted by the protocol whenever it gathers the correct ratios of all collateral tokens. This is the most efficient form of revenue capture, because it requires minimal trading of the excess collateral (and thus, a minimal spend on gas fees and trading slippage).
When the protocol is able to gather all the required parts of an RToken, these parts (collateral tokens) get sent to the RevenueTrader contract, where it performs an internal mint to create more RTokens. These new RTokens are then used as yield for both RToken holders and RSR stakers.
The backing buffer parameter is a percentage value that describes how much additional collateral tokens the protocol should hold on to before sending collateral tokens to the RevenueTraders. If this were set to “0”, then it’s possible (though unlikely) that collateral could “take turns” appreciating, causing the protocol to forward individual collateral tokens to the RevenueTraders and never assemble it into new RTokens.
Max trade slippage (%)
The maximum trade slippage is a percentage value that describes the maximum deviation from oracle prices that any trade that the protocol performs can clear at. Oracle prices have ranges of their own; the maximum trade slippage permits additional price movement beyond the worst-case oracle price.
Setting this percentage too high could cause the protocol to take high losses if auctions are illiquid.
Minimum trade volume
The minimum trade volume represents the smallest amount of value that is worth executing a trade for.
Setting this too high will result in auctions happening infrequently or the RToken taking a haircut when it cannot be sure it has enough staked RSR to succeed in rebalancing at par.
Setting this too low may allow griefers to delay important auctions. The variable should be set such that donations of size minTradeVolume would be worth delaying trading auctionLength seconds.
We expect auction bidders to pass-through any gas fees they pay during trading to the protocol. They are under competition, so those that do not will find themselves with less capital over time relative to those that do.
In order for the protocol not to take losses it’s important it knows that bidders will bid in the auction near market prices, which requires that gas prices are not significant relative to the volume of the auction.
Note: Every collateral in the basket should be a large enough portion of the basket that is worth trading at the configured minTradeVolume, even when we are only looking at 5% or 10% of its balance.
RToken max trade volume
This represents the maximum sized trade for any trade involving RToken, in terms of value.
It is important to remark that in addition to the RToken, each collateral plugin will also have its own max trade volume defined.
RToken supply throttles
In order to restrict the system to organic patterns of behavior, we maintain two supply throttles, one for net issuance and one for net redemption.
When a supply change occurs, a check is performed to ensure this does not move the supply more than an acceptable range over a period; a period is fixed to be an hour.
The throttling mechanism works as a battery, where, after a large issuance/redemption, the limit recharges linearly to the defined maximum at a defined speed of recharge.
Limits can be defined (for issuance and redemption) in rToken amounts and/or as a percentage of the RToken supply.
Issuance throttle amount
A quantity of RToken that serves as a lower-bound for how much net issuance to allow per hour. This quantity is defined in RToken amounts.
Must be at least 1 whole RToken. Can be set to a very high numer (e.g. 1e48) to effectively disable the issuance throttle.
Issuance throttle rate (%)
A fraction of the RToken supply that indicates how much net issuance to allow per hour.
Can even be set to 0, to solely rely on throttle amount.
Redemption throttle amount
A quantity of RToken that serves as a lower-bound for how much net redemption to allow per hour.
Defined in RToken amounts.
Must be at least 1 whole RToken. Can be set to a very high numer (e.g. 1e48) to effectively disable the redemption throttle.
Redemption throttle rate (%)
A fraction of the RToken supply that indicates how much net redemption to allow per hour.
Can be 0 to solely rely on the throttle amount.
Long freeze duration(s)
The number of seconds a long freeze lasts.
Long freezes can be disabled by removing all addresses associated to the role.
The unstaking delay is the number of seconds that all RSR unstakings must be delayed in order to account for stakers trying to frontrun defaults.
In the case of a collateral token default, RSR holders are not given a choice as to whether their RSR is used to cover the default, since selfish anonymous actors would often choose not to follow through. So, there must be a delay when withdrawing RSR from the staking contract.
In practice, whenever an RSR staker chooses to withdraw their RSR, they must submit a transaction, wait X amount of time, and then submit another transaction to complete the withdrawal. During the waiting period, their RSR continues to be subject to forfeiture in the case of a collateral token default, but stops earning its pro-rata share of the RToken’s revenue.
The goal of this delay is to make it so that at any point in time, staked RSR that has not had a withdrawal transaction initiated is at least X time away from being withdrawn.
Reward ratio (decimals)
The reward ratio is the percentage of the current reward amount that should be handed out per block.
Default value: 3209014700000 = a half life of 30 days at a period of 12s.
Mainnet reasonable range: 1e11 to 1e13
Use cases of RTokens
The RToken platform is a tool to aggregate relatively stable assets together to create basket-backed stablecoins. Our intention in the long term is to facilitate the creation of an asset-backed currency that is independent of fiat monetary systems. We envision this becoming possible once enough asset types are tokenized.
We are laying the groundwork early, as not many assets are tokenized yet. Today, the main use-cases we see are (1) a more decentralized USD-backed coin, which reduces dependence on any one fiatcoin issuer, and (2) a single simple USD-based coin that packages the yield of DeFi protocols.
The main purpose of allowing and encouraging many RTokens is so that open exploration and competition can lead to the discovery of the best type of basket and governance system. There's a lot to explore, and it's better not to keep that under the control of the initial founding team. That said, we still anticipate a single dominant RToken emerging over time through that evolutionary process, and we think consolidation into one or two dominant options is a good thing, since simplicity and ubiquity are important for an asset to really be a currency.
We also can imagine fintech companies using the protocol to launch their own branded basket-backed stablecoins, though this wasn't the central intent of opening up the platform.
We don't expect lots of RTokens to be created right after protocol launch. Rather, we think that if one or two RTokens become large and known, that will inspire the creation of more over time.