Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gas-optimization: remove unnecessary main.* calls #1025

Merged
merged 22 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from 21 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
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# Changelog

# 3.2.0

This release 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 Steps

Upgrade BasketHandler and Distributor

Call `Distributor.cacheComponents()` if this is the first upgrade to a >=3.0.0 token.

### Core Protocol Contracts

New governance param added to `DeploymentParams`: `reweightable`

- `BasketHandler` [+1 slot]
- Add concept of a reweightable basket: a basket that can have its target amounts (once grouped by target unit) changed
- Add immutable-after-init `reweightable` bool
- `Deployer`
- New boolean field `reweightable` added to `IDeployer.DeploymentParams`
- `Distributor`
- Minor gas-optimization

# 3.1.0 - Unreleased

### Upgrade Steps -- Required
Expand Down
1 change: 1 addition & 0 deletions common/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ export interface IConfig {
unstakingDelay: BigNumber
withdrawalLeak: BigNumber
warmupPeriod: BigNumber
reweightable: boolean
tradingDelay: BigNumber
batchAuctionLength: BigNumber
dutchAuctionLength: BigNumber
Expand Down
6 changes: 5 additions & 1 deletion contracts/interfaces/IBasketHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ interface IBasketHandler is IComponent {
event BasketStatusChanged(CollateralStatus oldStatus, CollateralStatus newStatus);

// Initialization
function init(IMain main_, uint48 warmupPeriod_) external;
function init(
IMain main_,
uint48 warmupPeriod_,
bool reweightable_
) external;

/// Set the prime basket
/// @param erc20s The collateral tokens for the new prime basket
Expand Down
1 change: 1 addition & 0 deletions contracts/interfaces/IDeployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct DeploymentParams {
//
// === BasketHandler ===
uint48 warmupPeriod; // {s} how long to wait until issuance/trading after regaining SOUND
bool reweightable; // whether the basket can change in value
//
// === BackingManager ===
uint48 tradingDelay; // {s} how long to wait until starting auctions after switching basket
Expand Down
16 changes: 13 additions & 3 deletions contracts/p0/BasketHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ contract BasketHandlerP0 is ComponentP0, IBasketHandler {
uint192 public constant MAX_TARGET_AMT = 1e3 * FIX_ONE; // {target/BU} max basket weight

// config is the basket configuration, from which basket will be computed in a basket-switch
// event. config is only modified by governance through setPrimeBakset and setBackupConfig
// event. config is only modified by governance through setPrimeBasket and setBackupConfig
BasketConfig private config;

// basket, disabled, nonce, and timestamp are only ever set by `_switchBasket()`
Expand Down Expand Up @@ -148,6 +148,9 @@ contract BasketHandlerP0 is ComponentP0, IBasketHandler {
// A history of baskets by basket nonce; includes current basket
mapping(uint48 => Basket) private basketHistory;

// Whether the total weights of the target basket can be changed
bool public reweightable; // immutable after init

// ==== Invariants ====
// basket is a valid Basket:
// basket.erc20s is a valid collateral array and basket.erc20s == keys(basket.refAmts)
Expand All @@ -158,10 +161,15 @@ contract BasketHandlerP0 is ComponentP0, IBasketHandler {
// if basket.erc20s is empty then disabled == true

// BasketHandler.init() just leaves the BasketHandler state zeroed
function init(IMain main_, uint48 warmupPeriod_) external initializer {
function init(
IMain main_,
uint48 warmupPeriod_,
bool reweightable_
) external initializer {
__Component_init(main_);

setWarmupPeriod(warmupPeriod_);
reweightable = reweightable_; // immutable thereafter

// Set last status to DISABLED (default)
lastStatus = CollateralStatus.DISABLED;
Expand Down Expand Up @@ -245,7 +253,9 @@ contract BasketHandlerP0 is ComponentP0, IBasketHandler {
requireValidCollArray(erc20s);

// If this isn't initial setup, require targets remain constant
if (config.erc20s.length > 0) requireConstantConfigTargets(erc20s, targetAmts);
if (!reweightable && config.erc20s.length > 0) {
requireConstantConfigTargets(erc20s, targetAmts);
}

// Clean up previous basket config
for (uint256 i = 0; i < config.erc20s.length; ++i) {
Expand Down
2 changes: 1 addition & 1 deletion contracts/p0/Deployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ contract DeployerP0 is IDeployer, Versioned {
);

// Init Basket Handler
main.basketHandler().init(main, params.warmupPeriod);
main.basketHandler().init(main, params.warmupPeriod, params.reweightable);

// Init Revenue Traders
main.rsrTrader().init(main, rsr, params.maxTradeSlippage, params.minTradeVolume);
Expand Down
35 changes: 26 additions & 9 deletions contracts/p1/BasketHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ contract BasketHandlerP1 is ComponentP1, IBasketHandler {
// Effectively local variable of `requireConstantConfigTargets()`
EnumerableMap.Bytes32ToUintMap private _targetAmts; // targetName -> {target/BU}

// ===
// Added in 3.2.0

// Whether the total weights of the target basket can be changed
bool public reweightable; // immutable after init

// ===

// ==== Invariants ====
Expand All @@ -91,7 +97,11 @@ contract BasketHandlerP1 is ComponentP1, IBasketHandler {
// if basket.erc20s is empty then disabled == true

// BasketHandler.init() just leaves the BasketHandler state zeroed
function init(IMain main_, uint48 warmupPeriod_) external initializer {
function init(
IMain main_,
uint48 warmupPeriod_,
bool reweightable_
) external initializer {
__Component_init(main_);

assetRegistry = main_.assetRegistry();
Expand All @@ -101,6 +111,7 @@ contract BasketHandlerP1 is ComponentP1, IBasketHandler {
stRSR = main_.stRSR();

setWarmupPeriod(warmupPeriod_);
reweightable = reweightable_; // immutable thereafter

// Set last status to DISABLED (default)
lastStatus = CollateralStatus.DISABLED;
Expand Down Expand Up @@ -174,16 +185,16 @@ contract BasketHandlerP1 is ComponentP1, IBasketHandler {
// config'.erc20s = erc20s
// config'.targetAmts[erc20s[i]] = targetAmts[i], for i from 0 to erc20s.length-1
// config'.targetNames[e] = assetRegistry.toColl(e).targetName, for e in erc20s
function setPrimeBasket(IERC20[] calldata erc20s, uint192[] calldata targetAmts)
external
governance
{
function setPrimeBasket(IERC20[] calldata erc20s, uint192[] calldata targetAmts) external {
requireGovernanceOnly();
require(erc20s.length > 0, "empty basket");
require(erc20s.length == targetAmts.length, "len mismatch");
requireValidCollArray(erc20s);

// If this isn't initial setup, require targets remain constant
if (config.erc20s.length > 0) requireConstantConfigTargets(erc20s, targetAmts);
if (!reweightable && config.erc20s.length > 0) {
requireConstantConfigTargets(erc20s, targetAmts);
}

// Clean up previous basket config
for (uint256 i = 0; i < config.erc20s.length; ++i) {
Expand Down Expand Up @@ -224,7 +235,8 @@ contract BasketHandlerP1 is ComponentP1, IBasketHandler {
bytes32 targetName,
uint256 max,
IERC20[] calldata erc20s
) external governance {
) external {
requireGovernanceOnly();
requireValidCollArray(erc20s);
BackupConfig storage conf = config.backups[targetName];
conf.max = max;
Expand Down Expand Up @@ -507,14 +519,19 @@ contract BasketHandlerP1 is ComponentP1, IBasketHandler {
// === Governance Setters ===

/// @custom:governance
function setWarmupPeriod(uint48 val) public governance {
function setWarmupPeriod(uint48 val) public {
requireGovernanceOnly();
require(val >= MIN_WARMUP_PERIOD && val <= MAX_WARMUP_PERIOD, "invalid warmupPeriod");
emit WarmupPeriodSet(warmupPeriod, val);
warmupPeriod = val;
}

// === Private ===

// contract-size-saver
// solhint-disable-next-line no-empty-blocks
function requireGovernanceOnly() private governance {}

/// Select and save the next basket, based on the BasketConfig and Collateral statuses
function _switchBasket() private {
// Mark basket disabled. Pause most protocol functions unless there is a next basket
Expand Down Expand Up @@ -673,5 +690,5 @@ contract BasketHandlerP1 is ComponentP1, IBasketHandler {
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[37] private __gap;
uint256[36] private __gap;
}
2 changes: 1 addition & 1 deletion contracts/p1/Deployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ contract DeployerP1 is IDeployer, Versioned {
);

// Init Basket Handler
components.basketHandler.init(main, params.warmupPeriod);
components.basketHandler.init(main, params.warmupPeriod, params.reweightable);

// Init Revenue Traders
components.rsrTrader.init(main, rsr, params.maxTradeSlippage, params.minTradeVolume);
Expand Down
18 changes: 9 additions & 9 deletions contracts/p1/Distributor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ contract DistributorP1 is ComponentP1, IDistributor {

IERC20 private rsr;
IERC20 private rToken;
address private furnace;
address private stRSR;
IFurnace private furnace;
IStRSR private stRSR;
address private rTokenTrader;
address private rsrTrader;

Expand Down Expand Up @@ -108,8 +108,8 @@ contract DistributorP1 is ComponentP1, IDistributor {
Transfer[] memory transfers = new Transfer[](destinations.length());
uint256 numTransfers;

address furnaceAddr = furnace; // gas-saver
address stRSRAddr = stRSR; // gas-saver
address furnaceAddr = address(furnace); // gas-saver
address stRSRAddr = address(stRSR); // gas-saver

bool accountRewards = false;

Expand Down Expand Up @@ -144,9 +144,9 @@ contract DistributorP1 is ComponentP1, IDistributor {
// Perform reward accounting
if (accountRewards) {
if (isRSR) {
main.stRSR().payoutRewards();
stRSR.payoutRewards();
} else {
main.furnace().melt();
furnace.melt();
}
}
}
Expand Down Expand Up @@ -176,7 +176,7 @@ contract DistributorP1 is ComponentP1, IDistributor {
function _setDistribution(address dest, RevenueShare memory share) internal {
require(dest != address(0), "dest cannot be zero");
require(
dest != furnace && dest != stRSR,
dest != address(furnace) && dest != address(stRSR),
"destination can not be furnace or strsr directly"
);
if (dest == FURNACE) require(share.rsrDist == 0, "Furnace must get 0% of RSR");
Expand Down Expand Up @@ -205,8 +205,8 @@ contract DistributorP1 is ComponentP1, IDistributor {
function cacheComponents() public {
rsr = main.rsr();
rToken = IERC20(address(main.rToken()));
furnace = address(main.furnace());
stRSR = address(main.stRSR());
furnace = main.furnace();
stRSR = main.stRSR();
rTokenTrader = address(main.rTokenTrader());
rsrTrader = address(main.rsrTrader());
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/plugins/assets/VersionedAsset.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity 0.8.19;
import "../../interfaces/IVersioned.sol";

// This value should be updated on each release
string constant ASSET_VERSION = "3.1.0";
string constant ASSET_VERSION = "3.2.0";

/**
* @title VersionedAsset
Expand Down
Loading
Loading