This release adds Arbitrum support by adjusting Furnace
/StRSR
/Governance
to function off of timestamp/timepoints, instead of discrete periods. This changes the interface of the governance voting token StRSR, making this a complicated and nuanced upgrade to get right.
Warning: Do not attempt to execute the steps below manually. They are only a high-level overview of the changes made in this release. It is recommended to use the 3.4.0 Upgrade spell located at spells/3_4_0.sol
and deployed to mainnet at 0xb1df3a104d73ff86f9aaab60b491a5c44b090391
and base at 0x1744c9933feb8e76563fce63d5c95a4e7f967c2a
. These deployments will only work for the 11 RTokens: eUSD, ETH+, hyUSD (mainnet), USDC+, USD3, rgUSD, hyUSD (base), bsdETH, iUSDC, Vaya, and MAAT.
High-level overview:
- Upgrade all core contracts and plugins. This includes ALL assets and trading plugins, including the RTokenAsset itself
- Update 3.4.0 ERC20s via
setPrimeBasket()
+setBackupConfig()
- Call
cacheComponents()
onBroker
if upgrading from >=3.0.0, and also onBackingManager
,Distributor
, and bothRevenueTraders
, if upgrading from <3.0.0 - Adjust Furnace melt + StRSR drip ratios to be based on 1s. For example: divide ratios by 12 if upgrading an RToken on ethereum mainnet
- Deploy new TimelockController + Governance contracts and rotate adminship of RTokens. This effectively creates a new DAO for each RToken
- The
tradingDelay
can also be safely set to 0. It was a training wheel and is no longer necessary
Throughout many core contracts negligible gas improvements have been applied. These are excluded from the list below.
BackingManager
- Remove requirement for empty block between auctions of same kind (auctions must still be in different blocks)
BasketHandler
- Set max number of backup erc20s: 64
- Require all collateral are SOUND during index RToken
setPrimeBasket()
Broker
- Switch to timestamp-based auctions
Furnace
- Switch to timestamp-based melting
StRSR
- Switch to timestamp-based RSR drip
StRSRP1Votes
- Switch to timestamp-based checkpointing
- Add IERC58505 support
clock() external view returns (uint48)
CLOCK_MODE() external view returns (string memory)
- Deprecate
EURT
- Rename
ZeroPrice()
error toInvalidPrice()
- aave-v3
- Add try-catch to
StaticATokenV3LM.metaDeposit()
- Add try-catch to
- compound-v3
- Fix allowance check in
claimTo()
to usemsg.sender
- Fix allowance check in
- curve/convex
- Add
CurveAppreciatingRTokenFiatCollateral
+CurveAppreciatingRTokenSelfReferentialCollateral
to supportETH+/ETH
curve pools in non-recursive cases - Modify
CurveStableRTokenMetapoolCollateral
to checkisReady()
andfullyCollateralized()
status of underlying RTokens; try-catch asset-registry refresh call.
- Add
- metamorpho
- Add
MetaMorphoFiatCollateral
+MetaMorphoSelfReferentialCollateral
to supportsteakUSDC
/steakUSDP
/bbUSDT
/Re7WETH
morpho blue managed vaults
- Add
- frax
- Add missing
defaultThreshold != 0
check
- Add missing
DutchTrade
- Switch to timestamp-based model
price(uint256 blockNumber)
->price(uint48 timestamp)
- Remove
startBlock() returns (uint256)
+endBlock() returns (uint256)
- Add
startTime() returns (uint48)
bid(uint256 blockNumber)
=>bid(uint48 timestamp)
Switch to new Facade singleton model with multiple facets
FacadeRead
=>ReadFacet
+MaxIssuableFacet
FacadeAct
=>ActFacet
FacadeMonitor remains independent.
Create new Governor Anastasius contract to supersede Governor Alexios. Required to work with new timepoint-based model in StRSRP1Votes.
name()
: "Governor Alexios" => "Governor Anastasius"quorum(uint256 blockNumber)
=>quorum(uint256 timepoint)
- Add IERC58505 support
clock() external view returns (uint48)
CLOCK_MODE() external view returns (string memory)
This release improves how collateral plugins price LP tokens and moves reward claiming out to the asset plugin level.
Swapout all collateral plugins with appreciation.
All collateral plugins should be upgraded. The compound-v2 ERC20 wrapper will be traded out for the raw underlying CToken, as well as aave-v3 USDC/USDCbC for canonical wrappers.
BackingManager
+RevenueTrader
- Change
claimRewards()
to delegatecall to the list of registered plugins
- Change
- aave-v3
- On mainnet: switch from one-off USDC wrapper to canonical USDC wrapper
- On base: switch from one-off USDbC wrapper to canonical USDC wrapper
- compound-v2
- Remove
CTokenWrapper
- Add reward claiming logic to
claimRewards()
- Emit
RewardsClaimed
event duringclaimRewards()
- Remove
- compound-v3
- Emit
RewardsClaimed
event duringclaimRewards()
- Emit
- curve
- Emit
RewardsClaimed
event duringclaimRewards()
- Emit
- convex
- Emit
RewardsClaimed
event duringclaimRewards()
- Add new
crvUSD-USDC
plugin
- Emit
- morpho-aave
- Emit
RewardsClaimed
event duringclaimRewards()
- Emit
- stargate
- Emit
RewardsClaimed
event duringclaimRewards()
- Emit
GnosisTrade
- Add
version()
getter
- Add
DutchTrade
- Add
version()
getter
- Add
FacadeMonitor.sol
- Update compound-v2 implemention to deal with with-wrappper and without-wrapper cases
This release makes bidding in dutch auctions easier for MEV searchers and gives new RTokens being deployed the option to enable a variable target basket, or to be "reweightable". An RToken that is not reweightable cannot have its target basket changed in terms of quantities of target units.
Upgrade BasketHandler, BackingManager, and Distributor.
Call broker.setDutchTradeImplementation(newGnosisTrade)
with the new DutchTrade
contract address.
If this is the first upgrade to a >= 3.0.0 token, call *.cacheComponents()
on all components.
For plugins, upgrade all plugins that contain an appreciating asset (not FiatCollateral. AppreciatingFiatCollateral etc) OR contain multiple oracle feeds.
New governance param added: reweightable
BackingManager
- Track basket nonce last collateralized at end of
settleTrade()
- Track basket nonce last collateralized at end of
BasketHandler
[+1 slot]- Restrict
redeemCustom()
to nonces afterlastCollateralized
- New
LastCollateralizedChanged()
event -- track to determine earliest basket nonce to use forredeemCustom()
- Add concept of a reweightable basket: a basket that can have its target amounts (once grouped by target unit) changed
- Add
reweightable()
view - Add
forceSetPrimeBasket()
to allow setting a new prime basket without normalizing by USD value - Alter
setPrimeBasket()
to enforce basket normalization for reweightable RTokens
- Restrict
BackingManager
- Minor gas optimization
Deployer
- New boolean field
reweightable
added toIDeployer.DeploymentParams
- New boolean field
Distributor
- Minor gas optimization
- frax-eth: Add new
sFrxETH
plugin that leverages a curve EMA - stargate: Continue transfers of wrapper tokens if stargate rewards break
- All plugins with variable refPerTok(): do not revert refresh() when underlying protocol reverts
- All plugins with multiple chainlink feeds will now timeout over the maximum of the feeds' timeouts
- Add ORACLE_TIMEOUT_BUFFER to all usages of chainlink feeds
FacadeRead
- Use avg prices instead of low prices in
backingOverview()
andbasketBreakdown()
- Use avg prices instead of low prices in
-
DutchTrade
- Add new
bidTradeCallback()
function to allow payment of tokens at the end of the tx, removing need for flash loans. Example of how-to-use incontracts/plugins/mocks/DutchTradeRouter.sol
FacadeRead
- Add
maxIssuableByAmounts()
function to provide an estimation independent of account balances
- Add
- Add new
Upgrade all core contracts and all assets. Most ERC20s do not need to be upgraded. Use Deployer.deployRTokenAsset()
to create a new RTokenAsset
instance. This asset should be swapped too.
ERC20s that do need to be upgraded:
- Morpho
- Convex
- CompoundV3
Then, call Broker.cacheComponents()
.
Finally, call Broker.setBatchTradeImplementation(newGnosisTrade)
.
BackingManager
[+2 slots]- Replace use of
lotPrice()
withprice()
everywhere - Track
tokensOut
on trades and account for during collateralization math - Call
StRSR.payoutRewards()
after forwarding RSR - Make
backingBuffer
math precise - Add caching in
RecollateralizationLibP1
- Use
price().low
instead ofprice().high
to compute maximum sell amounts
- Replace use of
BasketHandler
- Replace use of
lotPrice()
withprice()
everywhere - Minor gas optimizations to status tracking and custom redemption math
- Replace use of
Broker
[+1 slot]- Cache
rToken
address and addcacheComponents()
helper - Allow
reportViolation()
to be called when paused or frozen - Disallow starting dutch trades with non-RTokenAsset assets when
lastSave() != block.timestamp
- Cache
Distributor
- Call
RevenueTrader.distributeTokenToBuy()
before distribution table changes - Call
StRSR.payoutRewards()
orFurnace.melt()
after distributions - Minor gas optimizations
- Call
Furnace
- Allow melting while frozen
Main
- Remove
furnace.melt()
frompoke()
- Remove
RevenueTrader
- Replace use of
lotPrice()
withprice()
everywhere - Ensure
settleTrade
cannot be reverted due totokenToBuy
distribution - Ensure during
manageTokens()
that the Distributor is configured for thetokenToBuy
- Replace use of
StRSR
- Use correct era in
UnstakingStarted
event - Expose
draftEra
viagetDraftEra()
view
- Use correct era in
FacadeMonitor
- Add
batchAuctionsDisabled()
view - Add
dutchAuctionsDisabled()
view - Add
issuanceAvailable()
view - Add
redemptionAvailable()
view - Add
backingRedeemable()
view
- Add
FacadeRead
- Add
draftEra
argument topendingUnstakings()
- Remove
.melt()
calls during pokes
- Add
- ALL
- Deprecate
lotPrice()
- Alter
price().low
to decay downwards to 0 over the price timeout - Alter
price().high
to decay upwards to 3x over the price timeout - Move
ORACLE_TIMEOUT_BUFFER
into code, as opposed to incorporating at the deployment script level - Make
refPerTok()
smoother during event of hard default - Check for
defaultThreshold > 0
in constructors - Add 9 more decimals of precision to reward accounting (some wrappers excluded)
- Deprecate
- compoundv2: make wrapper much more gas efficient during COMP claim
- compoundv3 bugfix: check permission correctly on underlying comet
- curve: Also
refresh()
the RToken's AssetRegistry duringrefresh()
- convex: Update to latest approved wrapper from Convex team
- morpho-aave: Add ability to track and handout MORPHO rewards
- yearnv2: Use pricePerShare helper for more precision
- Add a minimum voting delay of 1 day
GnosisTrade
- Add
sellAmount() returns (uint192)
view
- Add
Update BackingManager
, both RevenueTraders
(rTokenTrader/rsrTrader), and call Broker.setBatchTradeImplementation()
passing in the new GnosisTrade
address.
Bump solidity version to 0.8.19
Update all component contracts, including Main.
Call the following functions:
BackingManager.cacheComponents()
RevenueTrader.cacheComponents()
(for both rsrTrader and rTokenTrader)Distributor.cacheComponents()
All asset plugins (and their corresponding ERC20s) must be upgraded. The only exception is the StaticATokenLM
ERC20s from Aave V2. These can be left the same, however their assets should upgraded.
- Note: Make sure to use
Deployer.deployRTokenAsset()
to create newRTokenAsset
instances. This asset should be swapped too.
Call the following functions, once it is desired to turn on the new features:
BasketHandler.setWarmupPeriod()
StRSR.setWithdrawalLeak()
Broker.setDutchAuctionLength()
Broker.setDutchTradeImplementation()
It is acceptable to leave these function calls out of the initial upgrade tx and follow up with them later. The protocol will continue to function, just without dutch auctions, RSR unstaking gas-savings, and the warmup period.
-
AssetRegistry
[+1 slot] Summary: Other component contracts need to know when refresh() was last called- Add
lastRefresh()
timestamp getter - Add
size()
getter for number of registered assets - Require asset is SOUND on registration
- Bugfix: Fix gas attack that could result in someone disabling the basket
- Add
-
BackingManager
[+2 slots] Summary: manageTokens was broken out into separate rebalancing and surplus-forwarding functions to allow users to more precisely call the protocol- Replace
manageTokens(IERC20[] memory erc20s)
with:rebalance(TradeKind)
- Modify trading algorithm to not trade RToken, and instead dissolve it when it has a balance above ~1e6 RToken quanta. "dissolve" = melt() with a basketsNeeded change, similar to redemption but without transfer of RToken collateral.
- Use
lotPrice()
to set trade prices instead ofprice()
- Add significant caching to save gas
forwardRevenue(IERC20[] memory erc20s)
- Modify backingBuffer logic to keep the backing buffer in collateral tokens only. Fix subtle and inconsequential bug that resulted in not maximizing RToken minting locally, though overall RToken production does not change.
- Use
nonReentrant
over CEI pattern for gas improvement. related to discussion of this cross-contract reentrancy risk
- move
nonReentrant
up outsidetryTrade
internal helper
- Remove
manageTokensSortedOrder(IERC20[] memory erc20s)
- Modify
settleTrade(IERC20 sell)
to callrebalance()
when caller is a trade it deployed. - Remove all
delegatecall
during reward claiming; callclaimRewards()
directly on ERC20 - Functions now revert on unproductive executions, instead of no-op
- Do not trade until a warmupPeriod (last time SOUND was newly attained) has passed
- Add
cacheComponents()
refresher to be called on upgrade - Add concept of
tradeNonce
- Bugfix: consider
maxTradeVolume()
from both assets on a trade, not just 1
- Replace
-
BasketHandler
[+5 slots] Summary: Introduces a notion of basket warmup to defend against short-term oracle manipulation attacks. Prevent RTokens from changing in value due to governance- Add new gov param:
warmupPeriod
with settersetWarmupPeriod(..)
and eventWarmupPeriodSet()
- Add
trackStatus()
refresher - Add
isReady()
view - Extract basket switching logic out into external library
BasketLibP1
- Enforce
setPrimeBasket()
does not change the net value of a basket in terms of its target units - Add
quoteCustomRedemption(uint48[] basketNonces, uint192[] memory portions, ..)
to quote a linear combination of current-or-previous baskets for redemption - Add
getHistoricalBasket(uint48 basketNonce)
view - Bugfix: Protect against high BU price overflow
- Add new gov param:
-
Broker
[+2 slot] Summary: Add a second trading method for single-lot dutch auctions. Batch auctions via Gnosis EasyAuction are expected to be the backup auction going forward.- Add new dutch auction
DutchTrade
- Add minimum auction length of 20 blocks based on network block time
- Rename variable
auctionLength
->batchAuctionLength
- Rename setter
setAuctionLength()
->setBatchAuctionLength()
- Rename event
AuctionLengthSet()
->BatchAuctionLengthSet()
- Add
dutchAuctionLength
andsetDutchAuctionLength()
setter andDutchAuctionLengthSet()
event - Add
dutchTradeImplementation
andsetDutchTradeImplementation()
setter andDutchTradeImplementationSet()
event - Modify
setBatchTradeDisabled(bool)
->enableBatchTrade()
- Modify
setDutchTradeDisabled(IERC20 erc20, bool)
->enableDutchTrade(IERC20 erc20)
- Unlike batch auctions, dutch auctions can be disabled per-ERC20, and can only be disabled by BackingManager-started trades
- Modify
openTrade(TradeRequest memory reg)
->openTrade(TradeKind kind, TradeRequest memory req, TradePrices memory prices)
- Allow when paused / frozen, since caller must be in-system
- Add new dutch auction
-
Deployer
[+0 slots] Summary: Support new governance params- Modify to handle new gov params:
warmupPeriod
,dutchAuctionLength
, andwithdrawalLeak
- Do not grant OWNER any of the roles other than ownership
- Add
deployRTokenAsset()
to allow easy creation of newRTokenAsset
instances
- Modify to handle new gov params:
-
Distributor
[+2 slots] Summary: Restrict callers to system components and remove paused/frozen checks- Remove
notPausedOrFrozen
modifier fromdistribute()
- Remove
-
Furnace
[+0 slots] Summary: Allow melting while paused- Allow melting while paused
- Melt during updates to the melting ratio
- Lower
MAX_RATIO
from 1e18 to 1e14.
-
Main
[+0 slots] Summary: Split pausing into two types of pausing: issuance and trading- Split
paused
intoissuancePaused
andtradingPaused
pause()
->pauseTrading()
andpauseIssuance()
unpause()
->unpauseTrading()
andunpauseIssuance()
pausedOrFrozen()
->tradingPausedOrFrozen()
andissuancePausedOrFrozen()
PausedSet()
event ->TradingPausedSet()
andIssuancePausedSet()
- Split
-
RevenueTrader
[+4 slots] Summary: QoL improvements. Make compatible with new dutch auction trading method- Remove
delegatecall
during reward claiming; callclaimRewards()
directly on ERC20 - Add
cacheComponents()
refresher to be called on upgrade manageToken(IERC20 sell)
->manageTokens(IERC20[] calldata erc20s, TradeKind[] memory kinds)
- Allow multiple auctions to be launched at once
- Allow opening dust auctions (i.e ignore
minTradeVolume
) - Revert on 0 balance or collision auction instead of no-op
- Refresh buy and sell asset before trade
settleTrade(IERC20)
now distributestokenToBuy
automatically, instead of requiring separatemanageToken(IERC20)
call- Add
returnTokens(IERC20[] memory erc20s)
to return tokens to the BackingManager when the distribution is set to 0 - Add concept of
tradeNonce
- Remove
-
RToken
[+0 slots] Summary: Provide multiple redemption methods for fullyCollateralized vs uncollateralized.- Gas: Remove
exchangeRateIsValidAfter
modifier from all functions exceptsetBasketsNeeded()
- Modify issuance
to revert before
warmupPeriod` - Modify
redeem(uint256 amount, uint48 basketNonce)
->redeem(uint256 amount)
. Redemptions are always on the current basket nonce and revert under partial redemption - Modify
redeemTo(address recipient, uint256 amount, uint48 basketNonce)
->redeemTo(address recipient, uint256 amount)
. Redemptions are on the current basket nonce and revert under partial redemption - Add new
redeemCustom(.., uint256 amount, uint48[] memory basketNonces, uint192[] memory portions, ..)
function to allow redemption from a linear combination of current and previous baskets. During rebalancing this method of redemption may provide a higher overall redemption value than prorata redemption on the current basket nonce would. - Modify
mint(address recipient, uint256 amtRToken)
->mint(uint256 amtRToken)
, since recipient is always BackingManager. Expand scope to include adjustments tobasketsNeeded
- Add
dissolve(uint256 amount)
: burns RToken and reducesbasketsNeeded
, similar to redemption. Only callable by BackingManager - Modify
setBasketsNeeded(..)
to revert when supply is 0 - Bugfix: Accumulate throttles upon change
- Gas: Remove
-
StRSR
[+2 slots] Summary: Add the ability to cancel unstakings and a withdrawal() gas-saver to allow small RSR amounts to be exempt from asset refreshes- Lower
MAX_REWARD_RATIO
from 1e18 to 1e14. - Remove duplicate
stakeRate()
getter (same as1 / exchangeRate()
) - Add
withdrawalLeak
gov param, withsetWithdrawalLeak(..)
setter andWithdrawalLeakSet()
event - Modify
withdraw()
to allow a small % of RSR to exit without paying to refresh all assets - Modify
withdraw()
to check forwarmupPeriod
- Add
cancelUnstake(uint256 endId)
to allow re-staking during unstaking - Add
UnstakingCancelled()
event - Allow payout of (already acquired) RSR rewards while frozen
- Add ability for governance to
resetStakes()
when stake rate falls outside (1e12, 1e24)
- Lower
-
StRSRVotes
[+0 slots]- Add
stakeAndDelegate(uint256 rsrAmount, address delegate)
function to encourage people to receive voting weight upon staking
- Add
Remove FacadeMonitor
- now redundant with nextRecollateralizationAuction()
and revenueOverview()
-
FacadeAct
Summary: Remove unusedgetActCalldata()
and add way to run revenue auctions- Remove
getActCalldata(..)
- Remove
canRunRecollateralizationAuctions(..)
- Remove
runRevenueAuctions(..)
- Add
revenueOverview(IRevenueTrader) returns ( IERC20[] memory erc20s, bool[] memory canStart, uint256[] memory surpluses, uint256[] memory minTradeAmounts)
- Add
nextRecollateralizationAuction(..) returns (bool canStart, IERC20 sell, IERC20 buy, uint256 sellAmount)
- Modify all functions to work on both 3.0.0 and 2.1.0 RTokens
- Remove
-
FacadeRead
Summary: Add new data summary views frontends may be interested in -
Remove
basketNonce
fromredeem(.., uint48 basketNonce)
-
Add
redeemCustom(.., uint48[] memory basketNonces, uint192[] memory portions)
callstatic to simulate multi-basket redemptions -
Remove
traderBalances(..)
-
Add
balancesAcrossAllTraders(IBackingManager) returns (IERC20[] memory erc20s, uint256[] memory balances, uint256[] memory balancesNeededByBackingManager)
-
FacadeWrite
Summary: More expressive and fine-grained control over the set of pausers and freezers- Do not automatically grant Guardian PAUSER/SHORT_FREEZER/LONG_FREEZER
- Do not automatically grant Owner PAUSER/SHORT_FREEZER/LONG_FREEZER
- Add ability to initialize with multiple pausers, short freezers, and long freezers
- Modify
setupGovernance(.., address owner, address guardian, address pauser)
->setupGovernance(.., GovernanceRoles calldata govRoles)
A cheaper, simpler, trading method. Intended to be the new dominant trading method, with GnosisTrade (batch auctions) available as a backup option. Generally speaking the batch auction length can be kept shorter than the dutch auction length.
DutchTrade implements a four-stage, single-lot, falling price dutch auction:
- In the first 20% of the auction, the price falls from 1000x the best price to the best price in a geometric/exponential decay as a price manipulation defense mechanism. Bids are not expected to occur (but note: unlike the GnosisTrade batch auction, this mechanism is not resistant to arbitrary price manipulation). If a bid occurs, then trading for the pair of tokens is disabled as long as the trade was started by the BackingManager.
- Between 20% and 45%, the price falls linearly from 1.5x the best price to the best price.
- Between 45% and 95%, the price falls linearly from the best price to the worst price.
- Over the last 5% of the auction, the price remains constant at the worst price.
Duration: 30 min (default)
- Add
version() return (string)
getter to pave way for separation of asset versioning and core protocol versioning - Deprecate
claimRewards()
- Add
lastSave()
toRTokenAsset
- Remove
CurveVolatileCollateral
- Switch
CToken*Collateral
(Compound V2) to using a CTokenVault ERC20 rather than the raw cToken - Bugfix:
lotPrice()
now begins at 100% the lastSavedPrice, instead of below 100%. It can be at 100% for up to the oracleTimeout in the worst-case. - Bugfix: Handle oracle deprecation as indicated by the
aggregator()
being set to the zero address - Bugfix:
AnkrStakedETHCollateral
/CBETHCollateral
/RethCollateral
now correctly detects soft default (note that Ankr still requires a new oracle before it can be deployed) - Bugfix: Adjust
Curve*Collateral
andRTokenAsset
to treat FIX_MAX correctly as +inf - Bugfix: Continue updating cached price after collateral default (impacts all appreciating collateral)
BasketHandler
- Bugfix for
getPrimeBasket()
view - Minor change to
_price()
rounding - Minor natspec improvement to
refreshBasket()
- Bugfix for
Broker
- Fix
GnosisTrade
trade implemention to treat defensive rounding by EasyAuction correctly - Add
setGnosis()
andsetTradeImplementation()
governance functions
- Fix
RToken
- Minor gas optimization added to
redeemTo
to use savedassetRegistry
variable
- Minor gas optimization added to
StRSR
- Expose RSR variables via
getDraftRSR()
,getStakeRSR()
, andgetTotalDrafts()
views
- Expose RSR variables via
FacadeRead
- Extend
issue()
to return the estimated USD value of deposits asdepositsUoA
- Add
traderBalances()
- Add
auctionsSettleable()
- Add
nextRecollateralizationAuction()
- Modify
backingOverview() to handle unpriced cases
- Extend
FacadeAct
- Add
runRevenueAuctions()
- Add
Across all collateral, tryPrice()
was updated to exclude revenueHiding considerations
- Deploy CRV + CVX plugins
- Add
AnkrStakedEthCollateral
+ tests + deployment/verification scripts for ankrETH - Add FluxFinance collateral tests + deployment/verification scripts for fUSDC, fUSDT, fDAI, and fFRAX
- Add CompoundV3
CTokenV3Collateral
+ tests + deployment/verification scripts for cUSDCV3 - Add Convex
CvxStableCollateral
+ tests + deployment/verification scripts for 3Pool - Add Convex
CvxVolatileCollateral
+ tests + deployment/verification scripts for Tricrypto - Add Convex
CvxStableMetapoolCollateral
+ tests + deployment/verification scripts for MIM/3Pool - Add Convex
CvxStableRTokenMetapoolCollateral
+ tests + deployment/verification scripts for eUSD/fraxBP - Add Frax
SFraxEthCollateral
+ tests + deployment/verification scripts for sfrxETH - Add Lido
LidoStakedEthCollateral
+ tests + deployment/verification scripts for wstETH - Add RocketPool
RethCollateral
+ tests + deployment/verification scripts for rETH
- Add generic collateral testing suite at
test/plugins/individual-collateral/collateralTests.ts
- Add EasyAuction regression test for Broker false positive (observed during USDC de-peg)
- Add EasyAuction extreme tests
- Add
docs/plugin-addresses.md
as well as accompanying script for generation atscripts/collateral-params.ts
- Add
docs/exhaustive-tests.md
to document running exhaustive tests on GCP
Candidate release for the "all clear" milestone. There wasn't any real usage of the 1.0.0/1.1.0 releases; this is the first release that we are going to spend real effort to remain backwards compatible with.
- Bump solidity version to 0.8.17
- Support multiple beneficiaries via the
FacadeWrite
- Add
RToken.issueTo(address recipient, uint256 amount, ..)
andRToken.redeemTo(address recipient, uint256 amount, ..)
to support issuance/redemption to a different address thanmsg.sender
- Add
RToken.redeem*(.., uint256 basketNonce)
to enable msg sender to control expectations around partial redemptions - Add
RToken.issuanceAvailable()
+RToken.redemptionAvailable()
- Add
FacadeRead.primeBasket()
+FacadeRead.backupConfig()
views - Many external libs moved to internal
- Switch from price point estimates to price ranges; all prices now have a
low
andhigh
. Impacted interface functions:IAsset.price()
IBasketHandler.price()
- Replace
IAsset.fallbackPrice()
withIAsset.lotPrice()
. The lot price is the current price when available, and a fallback price otherwise. - Introduce decaying fallback prices. Over a finite period of time the fallback price goes to zero, linearly.
- Remove
IAsset.pricePerTarget()
from asset interface - Remove rewards earning and sweeping from RToken
- Add
safeMulDivCeil()
toITrading
traders. Use when overflow is possible from 2 locations: - Introduce config struct to encapsulate Collateral constructor params more neatly
- In general it should be easier to write Collateral plugins. Implementors should only ever have to override 4 functions:
tryPrice()
,refPerTok()
,targetPerRef()
, andclaimRewards()
. - Add
.div(1 - maxTradeSlippage)
to calculation ofshortfallSlippage
in RecollateralizationLib.sol:L188. - FacadeRead:
- remove
.pendingIssuances()
+.endIdForVest()
- refactor calculations in
basketBreakdown()
- remove
- Bugfix: Fix claim rewards from traders in
FacadeAct
- Bugfix: Do not handout RSR rewards when no one is staked
- Bugfix: Support small redemptions even when the RToken supply is massive
- Bump component-wide
version()
getter to 2.0.0 - Remove non-atomic issuance
- Replace redemption battery with issuance and redemption throttles
amtRate
valid range:[1e18, 1e48]
pctRate
valid range:[0, 1e18]
- Fix Furnace/StRSR reward period to 12 seconds
- Gov params:
- --
rewardPeriod
- --
issuanceRate
- ++
issuanceThrottle
- ++
redemptionThrottle
- --
- Events:
- --
RToken.IssuanceStarted
- --
RToken.IssuancesCompleted
- --
RToken.IssuancesCanceled
Issuance( address indexed recipient, uint256 indexed amount, uint192 baskets )
->Issuance( address indexed issuer, address indexed recipient, uint256 indexed amount, uint192 baskets )
Redemption(address indexed recipient, uint256 indexed amount, uint192 baskets )
->Redemption(address indexed redeemer, address indexed recipient, uint256 indexed amount, uint192 baskets )
- ++
RToken.IssuanceThrottleSet
- ++
RToken.RedemptionThrottleSet
- --
- Allow redemption while DISABLED
- Allow
grantRTokenAllowances()
while paused - Add
RToken.monetizeDonations()
escape hatch for accidentally donated tokens - Collateral default threshold: 5% -> 1% (+ include oracleError)
- RecollateralizationLib: Tighter basket range during recollateralization. Will now do
minTradeVolume
-size auctions to fill in dust rather than haircut. - Remove StRSR.setName()/setSymbol()
- Prevent RToken exchange rate manipulation at low supply
- Prevent StRSR exchange rate manipulation at low supply
- Forward RSR directly to StRSR, bypassing RSRTrader
- Accumulate melting on
Furnace.setRatio()
- Payout RSR rewards on
StRSR.setRatio()
- Distinguish oracle timeouts when dealing with multiple oracles in one plugin
- Add safety during asset degregistration to ensure it is always possible to unregister an infinite-looping asset
- Fix
StRSR
/RToken
EIP712 typehash to use release version instead of "1" - Add
FacadeRead.redeem(IRToken rToken, uint256 amount, uint48 basketNonce)
to return the expected redemption quantities on the basketNonce, or revert - Integrate with OZ 4.7.3 Governance (changes to
quorum()
/tproposalThreshold()
)
- Introduce semantic versioning to the Deployer and RToken
RTokenCreated
event: addedversion
argument
event RTokenCreated(
IMain indexed main,
IRToken indexed rToken,
IStRSR stRSR,
address indexed owner
);
=>
event RTokenCreated(
IMain indexed main,
IRToken indexed rToken,
IStRSR stRSR,
address indexed owner,
string version
);
- Add
version()
getter on Deployer, Main, and all Components, via mix-in. To be updated with each subsequent release.
d757d3a5a6097ae42c71fc03a7c787ec001d2efc
(This release is the one from the canonical lauch onstage in Bogota. We were missing semantic versioning at the time, but we call this the 1.0.0 release retroactively.)