Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
210 changes: 210 additions & 0 deletions .openzeppelin/mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -17006,6 +17006,216 @@
}
}
}
},
"c9a48c64e356317d3aaf432cb8dbd74677c11911e6045f4df3e62d0f87dc5548": {
"address": "0x1aCfF3eB9E4250Fb75526ceb3ff3b05c0CCfa42D",
"txHash": "0x317d0b5dce1b58b362e92eb78391e536042ee34d52f035e097ce5e7360fc6573",
"layout": {
"solcVersion": "0.8.28",
"storage": [
{
"label": "_initialized",
"offset": 0,
"slot": "0",
"type": "t_uint8",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63",
"retypedFrom": "bool"
},
{
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "t_bool",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68"
},
{
"label": "__gap",
"offset": 0,
"slot": "1",
"type": "t_array(t_uint256)50_storage",
"contract": "ContextUpgradeable",
"src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40"
},
{
"label": "__gap",
"offset": 0,
"slot": "51",
"type": "t_array(t_uint256)50_storage",
"contract": "ERC1967UpgradeUpgradeable",
"src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169"
},
{
"label": "__gap",
"offset": 0,
"slot": "101",
"type": "t_array(t_uint256)50_storage",
"contract": "UUPSUpgradeable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111"
},
{
"label": "main",
"offset": 0,
"slot": "151",
"type": "t_contract(IMain)32072",
"contract": "ComponentP1",
"src": "contracts/p1/mixins/Component.sol:21"
},
{
"label": "__gap",
"offset": 0,
"slot": "152",
"type": "t_array(t_uint256)49_storage",
"contract": "ComponentP1",
"src": "contracts/p1/mixins/Component.sol:87"
},
{
"label": "basketHandler",
"offset": 0,
"slot": "201",
"type": "t_contract(IBasketHandler)30661",
"contract": "AssetRegistryP1",
"src": "contracts/p1/AssetRegistry.sol:20"
},
{
"label": "backingManager",
"offset": 0,
"slot": "202",
"type": "t_contract(IBackingManager)30389",
"contract": "AssetRegistryP1",
"src": "contracts/p1/AssetRegistry.sol:21"
},
{
"label": "_erc20s",
"offset": 0,
"slot": "203",
"type": "t_struct(AddressSet)22716_storage",
"contract": "AssetRegistryP1",
"src": "contracts/p1/AssetRegistry.sol:24"
},
{
"label": "assets",
"offset": 0,
"slot": "205",
"type": "t_mapping(t_contract(IERC20)13972,t_contract(IAsset)29994)",
"contract": "AssetRegistryP1",
"src": "contracts/p1/AssetRegistry.sol:27"
},
{
"label": "lastRefresh",
"offset": 0,
"slot": "206",
"type": "t_uint48",
"contract": "AssetRegistryP1",
"src": "contracts/p1/AssetRegistry.sol:31"
},
{
"label": "__gap",
"offset": 0,
"slot": "207",
"type": "t_array(t_uint256)46_storage",
"contract": "AssetRegistryP1",
"src": "contracts/p1/AssetRegistry.sol:297"
}
],
"types": {
"t_array(t_bytes32)dyn_storage": {
"label": "bytes32[]",
"numberOfBytes": "32"
},
"t_array(t_uint256)46_storage": {
"label": "uint256[46]",
"numberOfBytes": "1472"
},
"t_array(t_uint256)49_storage": {
"label": "uint256[49]",
"numberOfBytes": "1568"
},
"t_array(t_uint256)50_storage": {
"label": "uint256[50]",
"numberOfBytes": "1600"
},
"t_bool": {
"label": "bool",
"numberOfBytes": "1"
},
"t_bytes32": {
"label": "bytes32",
"numberOfBytes": "32"
},
"t_contract(IAsset)29994": {
"label": "contract IAsset",
"numberOfBytes": "20"
},
"t_contract(IBackingManager)30389": {
"label": "contract IBackingManager",
"numberOfBytes": "20"
},
"t_contract(IBasketHandler)30661": {
"label": "contract IBasketHandler",
"numberOfBytes": "20"
},
"t_contract(IERC20)13972": {
"label": "contract IERC20",
"numberOfBytes": "20"
},
"t_contract(IMain)32072": {
"label": "contract IMain",
"numberOfBytes": "20"
},
"t_mapping(t_bytes32,t_uint256)": {
"label": "mapping(bytes32 => uint256)",
"numberOfBytes": "32"
},
"t_mapping(t_contract(IERC20)13972,t_contract(IAsset)29994)": {
"label": "mapping(contract IERC20 => contract IAsset)",
"numberOfBytes": "32"
},
"t_struct(AddressSet)22716_storage": {
"label": "struct EnumerableSet.AddressSet",
"members": [
{
"label": "_inner",
"type": "t_struct(Set)22401_storage",
"offset": 0,
"slot": "0"
}
],
"numberOfBytes": "64"
},
"t_struct(Set)22401_storage": {
"label": "struct EnumerableSet.Set",
"members": [
{
"label": "_values",
"type": "t_array(t_bytes32)dyn_storage",
"offset": 0,
"slot": "0"
},
{
"label": "_indexes",
"type": "t_mapping(t_bytes32,t_uint256)",
"offset": 0,
"slot": "1"
}
],
"numberOfBytes": "64"
},
"t_uint256": {
"label": "uint256",
"numberOfBytes": "32"
},
"t_uint48": {
"label": "uint48",
"numberOfBytes": "6"
},
"t_uint8": {
"label": "uint8",
"numberOfBytes": "1"
}
}
}
}
}
}
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ This release implements a global lock on `Main` (by inherinting from `GlobalReen

This release prepares the core protocol for veRSR through the introduction of 3 registries (`DAOFeeRegistry`, `AssetPluginRegistry`, and `VersionRegistry`) and through restricting component upgrades to be handled by `Main`, where upgrade constraints can be enforced.

RTokenAsset.price() now reverts if the RTokenAsset is unpriced.

The release also expands collateral decimal support from 18 to 21, with some caveats about minimum token value. See [docs/solidity-style.md](./docs/solidity-style.md#Collateral-decimals) for more details.

Finally, it adds resistance to toxic issuance by charging more when the collateral is under peg.
Expand Down
26 changes: 15 additions & 11 deletions contracts/facade/facets/ActFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -114,19 +114,23 @@ contract ActFacet is Multicall {
}

surpluses[i] = erc20s[i].balanceOf(address(revenueTrader));
(uint192 low, ) = reg.assets[i].price(); // {UoA/tok}
if (low == 0) continue;

// {qTok} = {UoA} / {UoA/tok}
minTradeAmounts[i] = minTradeVolume.safeDiv(low, FLOOR).shiftl_toUint(
int8(reg.assets[i].erc20Decimals())
);
try reg.assets[i].price() returns (uint192 low, uint192) {
if (low == 0) continue;

// {qTok} = {UoA} / {UoA/tok}
minTradeAmounts[i] = minTradeVolume.safeDiv(low, FLOOR).shiftl_toUint(
int8(reg.assets[i].erc20Decimals())
);

if (
surpluses[i] > minTradeAmounts[i] &&
revenueTrader.trades(erc20s[i]) == ITrade(address(0))
) {
canStart[i] = true;
if (
surpluses[i] > minTradeAmounts[i] &&
revenueTrader.trades(erc20s[i]) == ITrade(address(0))
) {
canStart[i] = true;
}
} catch {
continue;
}
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IAsset.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface IAsset is IRewardable {
/// @dev Called immediately after deployment, before use
function refresh() external;

/// Should not revert
/// Should not revert (RTokenAsset exempt)
/// low should be nonzero if the asset could be worth selling
/// @return low {UoA/tok} The lower end of the price estimate
/// @return high {UoA/tok} The upper end of the price estimate
Expand Down
2 changes: 2 additions & 0 deletions contracts/p1/RevenueTrader.sol
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ contract RevenueTraderP1 is TradingP1, IRevenueTrader {
}

/// Return registered ERC20s to the BackingManager if distribution for tokenToBuy is 0
/// @dev Only intended to unstick tokens, not to support recollateralization efforts
/// @custom:interaction
function returnTokens(IERC20[] memory erc20s)
external
Expand All @@ -98,6 +99,7 @@ contract RevenueTraderP1 is TradingP1, IRevenueTrader {

/// Process some number of tokens
/// If the tokenToBuy is included in erc20s, RevenueTrader will distribute it at end of the tx
/// @dev If tokenToBuy is the RToken revenue processing halts if RTokenAsset.price() reverts
/// @param erc20s The ERC20s to manage; can be tokenToBuy or anything registered
/// @param kinds The kinds of auctions to launch: DUTCH_AUCTION | BATCH_AUCTION
/// @custom:interaction not strictly RCEI; nonReentrant
Expand Down
12 changes: 3 additions & 9 deletions contracts/plugins/assets/RTokenAsset.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ contract RTokenAsset is IAsset, VersionedAsset, IRTokenOracle {
/// in lending markets or anywhere where secondary market price is the central concern.
/// @return low {UoA/tok} The low price estimate
/// @return high {UoA/tok} The high price estimate
function tryPrice() external view virtual returns (uint192 low, uint192 high) {
function tryPrice() public view virtual returns (uint192 low, uint192 high) {
(uint192 lowBUPrice, uint192 highBUPrice) = basketHandler.price(true); // {UoA/BU}
require(lowBUPrice != 0 && highBUPrice != FIX_MAX, "invalid price");
assert(lowBUPrice <= highBUPrice); // not obviously true just by inspection
Expand Down Expand Up @@ -98,13 +98,7 @@ contract RTokenAsset is IAsset, VersionedAsset, IRTokenOracle {
/// @return {UoA/tok} The lower end of the price estimate
/// @return {UoA/tok} The upper end of the price estimate
function price() public view virtual returns (uint192, uint192) {
try this.tryPrice() returns (uint192 low, uint192 high) {
return (low, high);
} catch (bytes memory errData) {
// see: docs/solidity-style.md#Catching-Empty-Data
if (errData.length == 0) revert(); // solhint-disable-line reason-string
return (0, FIX_MAX);
}
return tryPrice();
}

/// Should not revert
Expand All @@ -113,7 +107,7 @@ contract RTokenAsset is IAsset, VersionedAsset, IRTokenOracle {
/// @return lotLow {UoA/tok} The lower end of the lot price estimate
/// @return lotHigh {UoA/tok} The upper end of the lot price estimate
function lotPrice() external view virtual returns (uint192 lotLow, uint192 lotHigh) {
return price();
return tryPrice();
}

/// @return {tok} The balance of the ERC20 in whole tokens
Expand Down
2 changes: 2 additions & 0 deletions contracts/plugins/assets/curve/CurveRecursiveCollateral.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import "../OracleLib.sol";
* @notice Collateral plugin for a CurveLP token for a pool between a
* a USD reference token and a USD RToken.
*
* @notice DEPRECATED
*
* Note:
* - The RToken _must_ be the same RToken using this plugin as collateral!
* - The RToken SHOULD have an RSR overcollateralization layer. DO NOT USE WITHOUT RSR!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ interface ICurveMetaPool is ICurvePool, IERC20Metadata {

/**
* @title CurveStableMetapoolCollateral
*
* @notice DEPRECATED in 4.0.0
*
* This plugin contract is intended for 2-fiattoken stable metapools that
* DO NOT involve RTokens, such as LUSD-fraxBP or MIM-3CRV.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import "./CurveStableMetapoolCollateral.sol";
* This plugin contract is intended for 2-fiattoken stable metapools that
* involve RTokens, such as eUSD-fraxBP.
*
* @notice DEPRECATED in 4.0.0
*
* tok = ConvexStakingWrapper(pairedUSDRToken/USDBasePool)
* ref = PairedUSDRToken/USDBasePool pool invariant
* tar = USD
Expand Down Expand Up @@ -142,6 +144,7 @@ contract CurveStableRTokenMetapoolCollateral is CurveStableMetapoolCollateral {
override
returns (uint192 lowPaired, uint192 highPaired)
{
// can revert if pairedToken is a >=4.0.0 RToken
return pairedAssetRegistry.toAsset(pairedToken).price();
}
}
Loading
Loading