Issue | Instances | |
---|---|---|
GAS-1 | Use assembly to check for address(0) |
62 |
GAS-2 | Using bools for storage incurs overhead | 5 |
GAS-3 | Cache array length outside of loop | 26 |
GAS-4 | State variables should be cached in stack variables rather than re-reading them from storage | 13 |
GAS-5 | Use calldata instead of memory for function arguments that do not get mutated | 48 |
GAS-6 | For Operations that will not overflow, you could use unchecked | 1735 |
GAS-7 | Use Custom Errors | 163 |
GAS-8 | Don't initialize variables with default value | 52 |
GAS-9 | Long revert strings | 16 |
GAS-10 | Functions guaranteed to revert when called by normal users can be marked payable |
14 |
GAS-11 | ++i costs less gas than i++ , especially when it's used in for -loops (--i /i-- too) |
11 |
GAS-12 | Using private rather than public for constants, saves gas |
36 |
GAS-13 | Use shift Right/Left instead of division/multiplication if possible | 5 |
GAS-14 | Splitting require() statements that use && saves gas | 10 |
GAS-15 | Use != 0 instead of > 0 for unsigned integer comparison | 63 |
GAS-16 | internal functions not called by the contract should be removed |
29 |
Saves 6 gas per instance
Instances (62):
File: contracts/mixins/Auth.sol
92: require(account != address(0), "cannot grant role to address 0");
File: contracts/mixins/ComponentRegistry.sol
37: require(address(val) != address(0), "invalid RToken address");
45: require(address(val) != address(0), "invalid StRSR address");
53: require(address(val) != address(0), "invalid AssetRegistry address");
61: require(address(val) != address(0), "invalid BasketHandler address");
69: require(address(val) != address(0), "invalid BackingManager address");
77: require(address(val) != address(0), "invalid Distributor address");
85: require(address(val) != address(0), "invalid RSRTrader address");
93: require(address(val) != address(0), "invalid RTokenTrader address");
101: require(address(val) != address(0), "invalid Furnace address");
109: require(address(val) != address(0), "invalid Broker address");
File: contracts/p1/BasketHandler.sol
404: if (address(erc20) == address(0)) continue;
File: contracts/p1/Broker.sol
129: require(address(newGnosis) != address(0), "invalid Gnosis address");
138: address(newTradeImplementation) != address(0),
160: address(newTradeImplementation) != address(0),
File: contracts/p1/Deployer.sol
49: address(rsr_) != address(0) &&
50: address(gnosis_) != address(0) &&
51: address(rsrAsset_) != address(0) &&
52: address(implementations_.main) != address(0) &&
53: address(implementations_.trading.gnosisTrade) != address(0) &&
54: address(implementations_.trading.dutchTrade) != address(0) &&
55: address(implementations_.components.assetRegistry) != address(0) &&
56: address(implementations_.components.backingManager) != address(0) &&
57: address(implementations_.components.basketHandler) != address(0) &&
58: address(implementations_.components.broker) != address(0) &&
59: address(implementations_.components.distributor) != address(0) &&
60: address(implementations_.components.furnace) != address(0) &&
61: address(implementations_.components.rsrTrader) != address(0) &&
62: address(implementations_.components.rTokenTrader) != address(0) &&
63: address(implementations_.components.rToken) != address(0) &&
64: address(implementations_.components.stRSR) != address(0),
110: require(owner != address(0) && owner != address(this), "invalid owner");
File: contracts/p1/Distributor.sol
158: require(dest != address(0), "dest cannot be zero");
File: contracts/p1/Main.sol
32: require(address(rsr_) != address(0), "invalid RSR address");
File: contracts/p1/RevenueTrader.sol
32: require(address(tokenToBuy_) != address(0), "invalid token address");
111: require(address(trades[erc20]) == address(0), "trade open");
File: contracts/p1/StRSR.sol
790: require(from != address(0), "ERC20: transfer from the zero address");
791: require(to != address(0), "ERC20: transfer to the zero address");
810: require(account != address(0), "ERC20: mint to the zero address");
826: require(account != address(0), "ERC20: burn from the zero address");
847: require(owner != address(0), "ERC20: approve from the zero address");
848: require(spender != address(0), "ERC20: approve to the zero address");
File: contracts/p1/StRSRVotes.sol
144: if (delegatee == address(0) && currentDelegate == address(0)) {
144: if (delegatee == address(0) && currentDelegate == address(0)) {
147: } else if (delegatee != address(0) && currentDelegate != delegatee) {
188: if (src != address(0)) {
197: if (dst != address(0)) {
File: contracts/p1/mixins/BasketLib.sol
293: if (address(erc20) == address(0)) return false;
File: contracts/p1/mixins/Component.sol
34: require(address(main_) != address(0), "main is zero address");
File: contracts/p1/mixins/RecollateralizationLib.sol
94: if (address(trade.sell) == address(0) || address(trade.buy) == address(0)) {
94: if (address(trade.sell) == address(0) || address(trade.buy) == address(0)) {
395: if (address(trade.sell) == address(0) && address(trade.buy) != address(0)) {
395: if (address(trade.sell) == address(0) && address(trade.buy) != address(0)) {
File: contracts/p1/mixins/Trading.sol
89: require(address(trade) != address(0), "no trade open");
116: assert(address(trades[sell]) == address(0));
File: contracts/plugins/trading/DutchTrade.sol
108: address(sell_) != address(0) &&
109: address(buy_) != address(0) &&
147: require(bidder == address(0), "bid already received");
177: if (bidder != address(0)) {
203: return status == TradeStatus.OPEN && (bidder != address(0) || block.timestamp > endTime);
File: contracts/plugins/trading/GnosisTrade.sol
92: assert(origin_ != address(0));
225: return data.clearingPriceOrder != bytes32(0);
Use uint256(1) and uint256(2) for true/false to avoid a Gwarmaccess (100 gas), and to avoid Gsset (20000 gas) when changing from ‘false’ to ‘true’, after having been ‘true’ in the past. See source.
Instances (5):
File: contracts/mixins/Auth.sol
45: bool public tradingPaused;
46: bool public issuancePaused;
File: contracts/p1/BasketHandler.sol
51: bool private disabled;
File: contracts/p1/Broker.sol
46: bool public disabled;
49: mapping(address => bool) private trades;
If not cached, the solidity compiler will always read the length of the array during each iteration. That is, if it is a storage array, this is an extra sload operation (100 additional extra gas for each iteration except for the first) and if it is a memory array, this is an extra mload operation (3 additional gas for each iteration except for the first).
Instances (26):
File: contracts/libraries/String.sol
14: for (uint256 i = 0; i < bStr.length; i++) {
File: contracts/p1/BasketHandler.sol
185: for (uint256 i = 0; i < config.erc20s.length; ++i) {
194: for (uint256 i = 0; i < erc20s.length; ++i) {
229: for (uint256 i = 0; i < erc20s.length; ++i) {
397: for (uint48 i = 0; i < basketNonces.length; ++i) {
402: for (uint256 j = 0; j < b.erc20s.length; ++j) {
568: for (uint256 i = 0; i < erc20s.length; i++) {
594: for (uint256 i = 0; i < b.erc20s.length; ++i) {
633: for (uint256 i = 0; i < erc20s.length; ++i) {
651: for (uint256 i = 0; i < erc20s.length; ++i) {
File: contracts/p1/Distributor.sol
104: for (uint256 i = 0; i < destinations.length(); ++i) {
File: contracts/p1/RToken.sol
144: for (uint256 i = 0; i < erc20s.length; ++i) {
207: for (uint256 i = 0; i < erc20s.length; ++i) {
264: for (uint256 i = 0; i < portions.length; ++i) {
292: for (uint256 i = 0; i < erc20sOut.length; ++i) {
306: for (uint256 i = 0; i < expectedERC20sOut.length; ++i) {
316: for (uint256 i = 0; i < erc20sOut.length; ++i) {
333: for (uint256 i = 0; i < expectedERC20sOut.length; ++i) {
File: contracts/p1/mixins/BasketLib.sol
175: for (uint256 i = 0; i < config.erc20s.length; ++i) {
193: for (uint256 i = 0; i < config.erc20s.length; ++i) {
248: for (uint256 j = 0; j < backup.erc20s.length && size < backup.max; ++j) {
259: for (uint256 j = 0; j < backup.erc20s.length && assigned < size; ++j) {
File: contracts/p1/mixins/RecollateralizationLib.sol
81: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
174: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
321: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
File: contracts/p1/mixins/RewardableLib.sol
27: for (uint256 i = 0; i < registry.erc20s.length; ++i) {
[GAS-4] State variables should be cached in stack variables rather than re-reading them from storage
The instances below point to the second+ access of a state variable within a function. Caching of a state variable replaces each Gwarmaccess (100 gas) with a much cheaper stack read. Other less obvious fixes/optimizations include having local memory caches of state variable structs, or having local caches of state variable contracts/addresses.
Saves 100 gas per instance
Instances (13):
File: contracts/p1/BasketHandler.sol
515: basketHistory[nonce].setFrom(_newBasket);
File: contracts/p1/RToken.sol
322: address(backingManager),
352: _scaleUp(address(backingManager), baskets, totalSupply());
481: emit BasketsNeededChanged(basketsNeeded, basketsNeeded + amtBaskets);
File: contracts/p1/RevenueTrader.sol
60: tokenToBuy.safeApprove(address(distributor), bal);
95: if (erc20 != IERC20(address(rToken)) && tokenToBuy != IERC20(address(rToken))) {
109: IAsset buy = assetRegistry.toAsset(tokenToBuy);
File: contracts/p1/mixins/Trading.sol
119: IERC20Upgradeable(address(sell)).safeApprove(address(broker), req.sellAmount);
File: contracts/plugins/trading/DutchTrade.sol
188: buy.safeTransfer(address(origin), boughtAmt);
File: contracts/plugins/trading/GnosisTrade.sol
131: IERC20Upgradeable(address(sell)).safeApprove(address(gnosis), initBal);
131: IERC20Upgradeable(address(sell)).safeApprove(address(gnosis), initBal);
137: endTime,
186: if (boughtAmt > 0) IERC20Upgradeable(address(buy)).safeTransfer(origin, boughtAmt);
Mark data types as calldata
instead of memory
where possible. This makes it so that the data is not automatically loaded into memory. If the data passed into the function does not need to be changed (like updating values in an array), it can be passed in as calldata
. The one exception to this is if the argument must later be passed into another function that takes an argument that specifies memory
storage.
Instances (48):
File: contracts/interfaces/IAssetRegistry.sol
34: function init(IMain main_, IAsset[] memory assets_) external;
File: contracts/interfaces/IBasketHandler.sol
62: function setPrimeBasket(IERC20[] memory erc20s, uint192[] memory targetAmts) external;
62: function setPrimeBasket(IERC20[] memory erc20s, uint192[] memory targetAmts) external;
129: uint48[] memory basketNonces,
130: uint192[] memory portions,
File: contracts/interfaces/IBroker.sol
48: function openTrade(TradeKind kind, TradeRequest memory req) external returns (ITrade);
File: contracts/interfaces/IDistributor.sol
40: function init(IMain main_, RevenueShare memory dist) external;
43: function setDistribution(address dest, RevenueShare memory share) external;
File: contracts/interfaces/IFacadeAct.sol
32: IERC20[] memory toSettle,
33: IERC20[] memory toStart,
File: contracts/interfaces/IGnosis.sol
37: bytes memory accessManagerContractData
File: contracts/interfaces/IMain.sol
174: Components memory components,
File: contracts/interfaces/IRToken.sol
63: string memory name_,
64: string memory symbol_,
65: string memory mandate_,
106: uint48[] memory basketNonces,
107: uint192[] memory portions,
108: address[] memory expectedERC20sOut,
109: uint256[] memory minAmounts
File: contracts/interfaces/IStRSR.sol
103: string memory name_,
104: string memory symbol_,
File: contracts/libraries/test/ArrayCallerMock.sol
8: function allUnique(IERC20[] memory arr) public pure returns (bool) {
12: function sortedAndAllUnique(IERC20[] memory arr) public pure returns (bool) {
File: contracts/libraries/test/StringCallerMock.sol
9: function toLower(string memory str) external pure returns (string memory){
File: contracts/p1/BasketHandler.sol
385: uint48[] memory basketNonces,
386: uint192[] memory portions,
File: contracts/p1/Broker.sol
97: function openTrade(TradeKind kind, TradeRequest memory req) external returns (ITrade) {
File: contracts/p1/Deployer.sol
46: Implementations memory implementations_
104: string memory name,
105: string memory symbol,
108: DeploymentParams memory params
File: contracts/p1/Distributor.sol
61: function setDistribution(address dest, RevenueShare memory share) external governance {
File: contracts/p1/Main.sol
27: Components memory components,
File: contracts/p1/RToken.sol
248: uint48[] memory basketNonces,
249: uint192[] memory portions,
250: address[] memory expectedERC20sOut,
251: uint256[] memory minAmounts
File: contracts/p1/mixins/RecollateralizationLib.sol
58: function prepareRecollateralizationTrade(IBackingManager bm, BasketRange memory basketsHeld)
File: contracts/plugins/governance/Governance.sol
94: address[] memory targets,
95: uint256[] memory values,
96: bytes[] memory calldatas,
97: string memory description
104: address[] memory targets,
105: uint256[] memory values,
106: bytes[] memory calldatas,
114: address[] memory targets,
115: uint256[] memory values,
116: bytes[] memory calldatas,
Instances (1735):
File: contracts/interfaces/IAsset.sol
4: import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
4: import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
4: import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
4: import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
4: import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
5: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
5: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
5: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
5: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
5: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
6: import "../libraries/Fixed.sol";
6: import "../libraries/Fixed.sol";
7: import "./IMain.sol";
8: import "./IRewardable.sol";
12: uint192 low; // {UoA/tok}
12: uint192 low; // {UoA/tok}
12: uint192 low; // {UoA/tok}
13: uint192 high; // {UoA/tok}
13: uint192 high; // {UoA/tok}
13: uint192 high; // {UoA/tok}
79: IFFY, // When a peg is not holding or a chainlink feed is stale
79: IFFY, // When a peg is not holding or a chainlink feed is stale
80: DISABLED // When the collateral has completely defaulted
80: DISABLED // When the collateral has completely defaulted
File: contracts/interfaces/IAssetRegistry.sol
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "./IAsset.sol";
6: import "./IComponent.sol";
File: contracts/interfaces/IBackingManager.sol
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "./IBroker.sol";
6: import "./IComponent.sol";
7: import "./ITrading.sol";
File: contracts/interfaces/IBasketHandler.sol
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "../libraries/Fixed.sol";
5: import "../libraries/Fixed.sol";
6: import "./IAsset.sol";
7: import "./IComponent.sol";
10: uint192 bottom; // {BU}
10: uint192 bottom; // {BU}
11: uint192 top; // {BU}
11: uint192 top; // {BU}
File: contracts/interfaces/IBroker.sol
4: import "./IAsset.sol";
5: import "./IComponent.sol";
6: import "./IGnosis.sol";
7: import "./ITrade.sol";
18: uint256 sellAmount; // {qSellTok}
18: uint256 sellAmount; // {qSellTok}
19: uint256 minBuyAmount; // {qBuyTok}
19: uint256 minBuyAmount; // {qBuyTok}
File: contracts/interfaces/IComponent.sol
4: import "./IMain.sol";
5: import "./IVersioned.sol";
File: contracts/interfaces/IDeployer.sol
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
5: import "../libraries/Throttle.sol";
5: import "../libraries/Throttle.sol";
6: import "./IAsset.sol";
7: import "./IDistributor.sol";
8: import "./IGnosis.sol";
9: import "./IMain.sol";
10: import "./IRToken.sol";
11: import "./IStRSR.sol";
12: import "./ITrade.sol";
13: import "./IVersioned.sol";
22: RevenueShare dist; // revenue sharing splits between RToken and RSR
22: RevenueShare dist; // revenue sharing splits between RToken and RSR
25: uint192 minTradeVolume; // {UoA}
25: uint192 minTradeVolume; // {UoA}
26: uint192 rTokenMaxTradeVolume; // {UoA}
26: uint192 rTokenMaxTradeVolume; // {UoA}
29: uint48 shortFreeze; // {s} how long an initial freeze lasts
29: uint48 shortFreeze; // {s} how long an initial freeze lasts
30: uint48 longFreeze; // {s} how long each freeze extension lasts
30: uint48 longFreeze; // {s} how long each freeze extension lasts
33: uint192 rewardRatio; // the fraction of available revenues that are paid out each 12s period
33: uint192 rewardRatio; // the fraction of available revenues that are paid out each 12s period
36: uint48 unstakingDelay; // {s} the "thawing time" of staked RSR before withdrawal
36: uint48 unstakingDelay; // {s} the "thawing time" of staked RSR before withdrawal
37: uint192 withdrawalLeak; // {1} fraction of RSR that can be withdrawn without refresh
37: uint192 withdrawalLeak; // {1} fraction of RSR that can be withdrawn without refresh
40: uint48 warmupPeriod; // {s} how long to wait until issuance/trading after regaining SOUND
40: uint48 warmupPeriod; // {s} how long to wait until issuance/trading after regaining SOUND
40: uint48 warmupPeriod; // {s} how long to wait until issuance/trading after regaining SOUND
43: uint48 tradingDelay; // {s} how long to wait until starting auctions after switching basket
43: uint48 tradingDelay; // {s} how long to wait until starting auctions after switching basket
44: uint48 batchAuctionLength; // {s} the length of a Gnosis EasyAuction
44: uint48 batchAuctionLength; // {s} the length of a Gnosis EasyAuction
45: uint48 dutchAuctionLength; // {s} the length of a falling-price dutch auction
45: uint48 dutchAuctionLength; // {s} the length of a falling-price dutch auction
45: uint48 dutchAuctionLength; // {s} the length of a falling-price dutch auction
46: uint192 backingBuffer; // {1} how much extra backing collateral to keep
46: uint192 backingBuffer; // {1} how much extra backing collateral to keep
47: uint192 maxTradeSlippage; // {1} max slippage acceptable in a trade
47: uint192 maxTradeSlippage; // {1} max slippage acceptable in a trade
50: ThrottleLib.Params issuanceThrottle; // see ThrottleLib
50: ThrottleLib.Params issuanceThrottle; // see ThrottleLib
File: contracts/interfaces/IDeployerRegistry.sol
4: import "./IDeployer.sol";
File: contracts/interfaces/IDistributor.sol
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "./IComponent.sol";
7: uint256 constant MAX_DISTRIBUTION = 1e4; // 10,000
7: uint256 constant MAX_DISTRIBUTION = 1e4; // 10,000
8: uint8 constant MAX_DESTINATIONS = 100; // maximum number of RevenueShare destinations
8: uint8 constant MAX_DESTINATIONS = 100; // maximum number of RevenueShare destinations
11: uint16 rTokenDist; // {revShare} A value between [0, 10,000]
11: uint16 rTokenDist; // {revShare} A value between [0, 10,000]
12: uint16 rsrDist; // {revShare} A value between [0, 10,000]
12: uint16 rsrDist; // {revShare} A value between [0, 10,000]
17: uint24 rTokenTotal; // {revShare}
17: uint24 rTokenTotal; // {revShare}
18: uint24 rsrTotal; // {revShare}
18: uint24 rsrTotal; // {revShare}
File: contracts/interfaces/IFacadeAct.sol
4: import "../interfaces/IBackingManager.sol";
4: import "../interfaces/IBackingManager.sol";
5: import "../interfaces/IRevenueTrader.sol";
5: import "../interfaces/IRevenueTrader.sol";
6: import "../interfaces/IRToken.sol";
6: import "../interfaces/IRToken.sol";
15: v */
15: v */
File: contracts/interfaces/IFacadeRead.sol
4: import "../p1/RToken.sol";
4: import "../p1/RToken.sol";
5: import "./IRToken.sol";
6: import "./IStRSR.sol";
13: v */
13: v */
File: contracts/interfaces/IFacadeTest.sol
4: import "./IRToken.sol";
5: import "./IStRSR.sol";
File: contracts/interfaces/IFacadeWrite.sol
4: import "./IDeployer.sol";
59: uint256 votingDelay; // in blocks
59: uint256 votingDelay; // in blocks
60: uint256 votingPeriod; // in blocks
60: uint256 votingPeriod; // in blocks
61: uint256 proposalThresholdAsMicroPercent; // e.g. 1e4 for 0.01%
61: uint256 proposalThresholdAsMicroPercent; // e.g. 1e4 for 0.01%
62: uint256 quorumPercent; // e.g 4 for 4%
62: uint256 quorumPercent; // e.g 4 for 4%
63: uint256 timelockDelay; // in seconds (used for timelock)
63: uint256 timelockDelay; // in seconds (used for timelock)
File: contracts/interfaces/IFurnace.sol
4: import "../libraries/Fixed.sol";
4: import "../libraries/Fixed.sol";
5: import "./IComponent.sol";
File: contracts/interfaces/IGnosis.sol
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
File: contracts/interfaces/IMain.sol
4: import "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6: import "./IAssetRegistry.sol";
7: import "./IBasketHandler.sol";
8: import "./IBackingManager.sol";
9: import "./IBroker.sol";
10: import "./IGnosis.sol";
11: import "./IFurnace.sol";
12: import "./IDistributor.sol";
13: import "./IRToken.sol";
14: import "./IRevenueTrader.sol";
15: import "./IStRSR.sol";
16: import "./ITrading.sol";
17: import "./IVersioned.sol";
21: uint48 constant ONE_BLOCK = 12; //{s}
21: uint48 constant ONE_BLOCK = 12; //{s}
167: function poke() external; // not used in p1
167: function poke() external; // not used in p1
File: contracts/interfaces/IRToken.sol
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
7: import "../libraries/Fixed.sol";
7: import "../libraries/Fixed.sol";
8: import "../libraries/Throttle.sol";
8: import "../libraries/Throttle.sol";
9: import "./IAsset.sol";
10: import "./IComponent.sol";
11: import "./IMain.sol";
12: import "./IRewardable.sol";
File: contracts/interfaces/IRevenueTrader.sol
4: import "./IBroker.sol";
5: import "./IComponent.sol";
6: import "./ITrading.sol";
File: contracts/interfaces/IRewardable.sol
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "./IComponent.sol";
6: import "./IMain.sol";
File: contracts/interfaces/IStRSR.sol
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
7: import "../libraries/Fixed.sol";
7: import "../libraries/Fixed.sol";
8: import "./IComponent.sol";
9: import "./IMain.sol";
File: contracts/interfaces/IStRSRVotes.sol
4: import "@openzeppelin/contracts-upgradeable/governance/utils/IVotesUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/governance/utils/IVotesUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/governance/utils/IVotesUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/governance/utils/IVotesUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/governance/utils/IVotesUpgradeable.sol";
File: contracts/interfaces/ITrade.sol
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
5: import "./IBroker.sol";
8: NOT_STARTED, // before init()
8: NOT_STARTED, // before init()
9: OPEN, // after init() and before settle()
9: OPEN, // after init() and before settle()
10: CLOSED, // after settle()
10: CLOSED, // after settle()
12: PENDING // during init() or settle() (reentrancy protection)
12: PENDING // during init() or settle() (reentrancy protection)
File: contracts/interfaces/ITrading.sol
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "../libraries/Fixed.sol";
5: import "../libraries/Fixed.sol";
6: import "./IAsset.sol";
7: import "./IComponent.sol";
8: import "./ITrade.sol";
9: import "./IRewardable.sol";
File: contracts/libraries/Array.sol
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
11: for (uint256 i = 1; i < arrLen; ++i) {
11: for (uint256 i = 1; i < arrLen; ++i) {
12: for (uint256 j = 0; j < i; ++j) {
12: for (uint256 j = 0; j < i; ++j) {
23: for (uint256 i = 1; i < arrLen; ++i) {
23: for (uint256 i = 1; i < arrLen; ++i) {
24: if (uint160(address(arr[i])) <= uint160(address(arr[i - 1]))) return false;
File: contracts/libraries/Fixed.sol
10: "fixed192x18" -- a value represented by 192 bits, that makes 18 digits available to
10: "fixed192x18" -- a value represented by 192 bits, that makes 18 digits available to
13: The range of values that uint192 can represent is about [-1.7e20, 1.7e20].
48: uint192 constant FIX_MAX_INT = type(uint192).max / FIX_SCALE;
50: uint192 constant FIX_ZERO = 0; // The uint192 representation of zero.
50: uint192 constant FIX_ZERO = 0; // The uint192 representation of zero.
51: uint192 constant FIX_ONE = FIX_SCALE; // The uint192 representation of one.
51: uint192 constant FIX_ONE = FIX_SCALE; // The uint192 representation of one.
52: uint192 constant FIX_MAX = type(uint192).max; // The largest uint192. (Not an integer!)
52: uint192 constant FIX_MAX = type(uint192).max; // The largest uint192. (Not an integer!)
53: uint192 constant FIX_MIN = 0; // The smallest uint192.
53: uint192 constant FIX_MIN = 0; // The smallest uint192.
57: FLOOR, // Round towards zero
57: FLOOR, // Round towards zero
58: ROUND, // Round to the nearest int
58: ROUND, // Round to the nearest int
59: CEIL // Round away from zero
59: CEIL // Round away from zero
67: Thus, all the tedious-looking double conversions like uint256(uint256 (foo))
68: See: https://docs.soliditylang.org/en/v0.8.17/080-breaking-changes.html#new-restrictions
68: See: https://docs.soliditylang.org/en/v0.8.17/080-breaking-changes.html#new-restrictions
68: See: https://docs.soliditylang.org/en/v0.8.17/080-breaking-changes.html#new-restrictions
68: See: https://docs.soliditylang.org/en/v0.8.17/080-breaking-changes.html#new-restrictions
68: See: https://docs.soliditylang.org/en/v0.8.17/080-breaking-changes.html#new-restrictions
68: See: https://docs.soliditylang.org/en/v0.8.17/080-breaking-changes.html#new-restrictions
68: See: https://docs.soliditylang.org/en/v0.8.17/080-breaking-changes.html#new-restrictions
68: See: https://docs.soliditylang.org/en/v0.8.17/080-breaking-changes.html#new-restrictions
81: return _safeWrap(x * FIX_SCALE);
101: if (shiftLeft <= -96) return (rounding == CEIL ? 1 : 0); // 0 < uint.max / 10**77 < 0.5
101: if (shiftLeft <= -96) return (rounding == CEIL ? 1 : 0); // 0 < uint.max / 10**77 < 0.5
101: if (shiftLeft <= -96) return (rounding == CEIL ? 1 : 0); // 0 < uint.max / 10**77 < 0.5
101: if (shiftLeft <= -96) return (rounding == CEIL ? 1 : 0); // 0 < uint.max / 10**77 < 0.5
101: if (shiftLeft <= -96) return (rounding == CEIL ? 1 : 0); // 0 < uint.max / 10**77 < 0.5
101: if (shiftLeft <= -96) return (rounding == CEIL ? 1 : 0); // 0 < uint.max / 10**77 < 0.5
102: if (40 <= shiftLeft) revert UIntOutOfBounds(); // 10**56 < FIX_MAX < 10**57
102: if (40 <= shiftLeft) revert UIntOutOfBounds(); // 10**56 < FIX_MAX < 10**57
102: if (40 <= shiftLeft) revert UIntOutOfBounds(); // 10**56 < FIX_MAX < 10**57
102: if (40 <= shiftLeft) revert UIntOutOfBounds(); // 10**56 < FIX_MAX < 10**57
102: if (40 <= shiftLeft) revert UIntOutOfBounds(); // 10**56 < FIX_MAX < 10**57
102: if (40 <= shiftLeft) revert UIntOutOfBounds(); // 10**56 < FIX_MAX < 10**57
104: shiftLeft += 18;
106: uint256 coeff = 10**abs(shiftLeft);
106: uint256 coeff = 10**abs(shiftLeft);
107: uint256 shifted = (shiftLeft >= 0) ? x * coeff : _divrnd(x, coeff, rounding);
119: if (x < uint256(type(uint256).max / FIX_SCALE_SQ)) {
120: return _safeWrap(uint256(x * FIX_SCALE_SQ) / y);
120: return _safeWrap(uint256(x * FIX_SCALE_SQ) / y);
148: return x < 0 ? uint256(-x) : uint256(x);
159: uint256 result = numerator / divisor;
164: if (numerator % divisor > (divisor - 1) / 2) {
164: if (numerator % divisor > (divisor - 1) / 2) {
165: result++;
165: result++;
169: result++;
169: result++;
212: if (decimals <= -59) return (rounding == CEIL ? 1 : 0); // 59, because 1e58 > 2**192
212: if (decimals <= -59) return (rounding == CEIL ? 1 : 0); // 59, because 1e58 > 2**192
212: if (decimals <= -59) return (rounding == CEIL ? 1 : 0); // 59, because 1e58 > 2**192
212: if (decimals <= -59) return (rounding == CEIL ? 1 : 0); // 59, because 1e58 > 2**192
212: if (decimals <= -59) return (rounding == CEIL ? 1 : 0); // 59, because 1e58 > 2**192
213: if (58 <= decimals) revert UIntOutOfBounds(); // 58, because x * 1e58 > 2 ** 192 if x != 0
213: if (58 <= decimals) revert UIntOutOfBounds(); // 58, because x * 1e58 > 2 ** 192 if x != 0
213: if (58 <= decimals) revert UIntOutOfBounds(); // 58, because x * 1e58 > 2 ** 192 if x != 0
213: if (58 <= decimals) revert UIntOutOfBounds(); // 58, because x * 1e58 > 2 ** 192 if x != 0
213: if (58 <= decimals) revert UIntOutOfBounds(); // 58, because x * 1e58 > 2 ** 192 if x != 0
215: uint256 coeff = uint256(10**abs(decimals));
215: uint256 coeff = uint256(10**abs(decimals));
216: return _safeWrap(decimals >= 0 ? x * coeff : _divrnd(x, coeff, rounding));
223: return x + y;
230: return _safeWrap(x + y * FIX_SCALE);
230: return _safeWrap(x + y * FIX_SCALE);
237: return x - y;
244: return _safeWrap(uint256(x) - uint256(y * FIX_SCALE));
244: return _safeWrap(uint256(x) - uint256(y * FIX_SCALE));
263: return _safeWrap(_divrnd(uint256(x) * uint256(y), FIX_SCALE, rounding));
270: return _safeWrap(x * y);
289: return _safeWrap(_divrnd(uint256(x) * FIX_SCALE, y, rounding));
310: uint64 constant FIX_HALF = uint64(FIX_SCALE) / 2;
320: uint256 x = uint256(x_) * FIX_SCALE; // x is D36
320: uint256 x = uint256(x_) * FIX_SCALE; // x is D36
320: uint256 x = uint256(x_) * FIX_SCALE; // x is D36
321: uint256 result = FIX_SCALE_SQ; // result is D36
321: uint256 result = FIX_SCALE_SQ; // result is D36
323: if (y & 1 == 1) result = (result * x + FIX_SCALE_SQ / 2) / FIX_SCALE_SQ;
323: if (y & 1 == 1) result = (result * x + FIX_SCALE_SQ / 2) / FIX_SCALE_SQ;
323: if (y & 1 == 1) result = (result * x + FIX_SCALE_SQ / 2) / FIX_SCALE_SQ;
323: if (y & 1 == 1) result = (result * x + FIX_SCALE_SQ / 2) / FIX_SCALE_SQ;
326: x = (x * x + FIX_SCALE_SQ / 2) / FIX_SCALE_SQ;
326: x = (x * x + FIX_SCALE_SQ / 2) / FIX_SCALE_SQ;
326: x = (x * x + FIX_SCALE_SQ / 2) / FIX_SCALE_SQ;
326: x = (x * x + FIX_SCALE_SQ / 2) / FIX_SCALE_SQ;
328: return _safeWrap(result / FIX_SCALE);
364: uint192 diff = x <= y ? y - x : x - y;
364: uint192 diff = x <= y ? y - x : x - y;
388: if (x == 0) return 0; // always computable, no matter what decimals is
388: if (x == 0) return 0; // always computable, no matter what decimals is
389: if (decimals <= -42) return (rounding == CEIL ? 1 : 0);
392: decimals -= 18; // shift so that toUint happens at the same time.
392: decimals -= 18; // shift so that toUint happens at the same time.
392: decimals -= 18; // shift so that toUint happens at the same time.
394: uint256 coeff = uint256(10**abs(decimals));
394: uint256 coeff = uint256(10**abs(decimals));
395: return decimals >= 0 ? uint256(x * coeff) : uint256(_divrnd(x, coeff, rounding));
504: uint256 rawDelta = uint256(b) * a; // {D36} = {D18} * {D18}
504: uint256 rawDelta = uint256(b) * a; // {D36} = {D18} * {D18}
504: uint256 rawDelta = uint256(b) * a; // {D36} = {D18} * {D18}
504: uint256 rawDelta = uint256(b) * a; // {D36} = {D18} * {D18}
506: if (rawDelta / b != a) return FIX_MAX;
510: if (rounding == RoundingMode.ROUND) shiftDelta += (FIX_ONE / 2);
510: if (rounding == RoundingMode.ROUND) shiftDelta += (FIX_ONE / 2);
511: else if (rounding == RoundingMode.CEIL) shiftDelta += FIX_ONE - 1;
511: else if (rounding == RoundingMode.CEIL) shiftDelta += FIX_ONE - 1;
529: if (shiftDelta / FIX_ONE > FIX_MAX) return FIX_MAX;
532: return uint192(shiftDelta / FIX_ONE); // {D18} = {D36} / {D18}
532: return uint192(shiftDelta / FIX_ONE); // {D18} = {D36} / {D18}
532: return uint192(shiftDelta / FIX_ONE); // {D18} = {D36} / {D18}
532: return uint192(shiftDelta / FIX_ONE); // {D18} = {D36} / {D18}
556: if (mm > lo) hi -= 1;
557: lo -= mm;
558: uint256 pow2 = z & (0 - z);
559: z /= pow2;
560: lo /= pow2;
561: lo += hi * ((0 - pow2) / pow2 + 1);
561: lo += hi * ((0 - pow2) / pow2 + 1);
561: lo += hi * ((0 - pow2) / pow2 + 1);
561: lo += hi * ((0 - pow2) / pow2 + 1);
561: lo += hi * ((0 - pow2) / pow2 + 1);
563: r *= 2 - z * r;
563: r *= 2 - z * r;
563: r *= 2 - z * r;
564: r *= 2 - z * r;
564: r *= 2 - z * r;
564: r *= 2 - z * r;
565: r *= 2 - z * r;
565: r *= 2 - z * r;
565: r *= 2 - z * r;
566: r *= 2 - z * r;
566: r *= 2 - z * r;
566: r *= 2 - z * r;
567: r *= 2 - z * r;
567: r *= 2 - z * r;
567: r *= 2 - z * r;
568: r *= 2 - z * r;
568: r *= 2 - z * r;
568: r *= 2 - z * r;
569: r *= 2 - z * r;
569: r *= 2 - z * r;
569: r *= 2 - z * r;
570: r *= 2 - z * r;
570: r *= 2 - z * r;
570: r *= 2 - z * r;
571: result = lo * r;
589: if (mm > 0) result += 1;
591: if (mm > ((z - 1) / 2)) result += 1; // z should be z-1
591: if (mm > ((z - 1) / 2)) result += 1; // z should be z-1
591: if (mm > ((z - 1) / 2)) result += 1; // z should be z-1
591: if (mm > ((z - 1) / 2)) result += 1; // z should be z-1
591: if (mm > ((z - 1) / 2)) result += 1; // z should be z-1
591: if (mm > ((z - 1) / 2)) result += 1; // z should be z-1
604: uint256 mm = mulmod(x, y, uint256(0) - uint256(1));
605: lo = x * y;
606: hi = mm - lo;
607: if (mm < lo) hi -= 1;
File: contracts/libraries/Permit.sol
4: import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/utils/cryptography/SignatureCheckerUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/utils/cryptography/SignatureCheckerUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/utils/cryptography/SignatureCheckerUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/utils/cryptography/SignatureCheckerUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/utils/cryptography/SignatureCheckerUpgradeable.sol";
File: contracts/libraries/String.sol
14: for (uint256 i = 0; i < bStr.length; i++) {
14: for (uint256 i = 0; i < bStr.length; i++) {
18: bLower[i] = bytes1(uint8(bStr[i]) + 32);
File: contracts/libraries/Throttle.sol
4: import "./Fixed.sol";
6: uint48 constant ONE_HOUR = 3600; // {seconds/hour}
6: uint48 constant ONE_HOUR = 3600; // {seconds/hour}
6: uint48 constant ONE_HOUR = 3600; // {seconds/hour}
21: uint256 amtRate; // {qRTok/hour} a quantity of RToken hourly; cannot be 0
21: uint256 amtRate; // {qRTok/hour} a quantity of RToken hourly; cannot be 0
21: uint256 amtRate; // {qRTok/hour} a quantity of RToken hourly; cannot be 0
22: uint192 pctRate; // {1/hour} a fraction of RToken hourly; can be 0
22: uint192 pctRate; // {1/hour} a fraction of RToken hourly; can be 0
22: uint192 pctRate; // {1/hour} a fraction of RToken hourly; can be 0
29: uint48 lastTimestamp; // {seconds}
29: uint48 lastTimestamp; // {seconds}
30: uint256 lastAvailable; // {qRTok}
30: uint256 lastAvailable; // {qRTok}
46: uint256 limit = hourlyLimit(throttle, supply); // {qRTok}
46: uint256 limit = hourlyLimit(throttle, supply); // {qRTok}
54: available -= uint256(amount);
57: available += uint256(-amount);
57: available += uint256(-amount);
72: uint48 delta = uint48(block.timestamp) - throttle.lastTimestamp; // {seconds}
72: uint48 delta = uint48(block.timestamp) - throttle.lastTimestamp; // {seconds}
72: uint48 delta = uint48(block.timestamp) - throttle.lastTimestamp; // {seconds}
73: available = throttle.lastAvailable + (limit * delta) / ONE_HOUR;
73: available = throttle.lastAvailable + (limit * delta) / ONE_HOUR;
73: available = throttle.lastAvailable + (limit * delta) / ONE_HOUR;
86: limit = (supply * params.pctRate) / FIX_ONE_256; // {qRTok}
86: limit = (supply * params.pctRate) / FIX_ONE_256; // {qRTok}
86: limit = (supply * params.pctRate) / FIX_ONE_256; // {qRTok}
86: limit = (supply * params.pctRate) / FIX_ONE_256; // {qRTok}
File: contracts/libraries/test/ArrayCallerMock.sol
4: import "../Array.sol";
File: contracts/libraries/test/FixedCallerMock.sol
4: import "../Fixed.sol";
File: contracts/libraries/test/StringCallerMock.sol
4: import "../String.sol";
File: contracts/mixins/Auth.sol
4: import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
5: import "../interfaces/IMain.sol";
5: import "../interfaces/IMain.sol";
7: uint256 constant LONG_FREEZE_CHARGES = 6; // 6 uses
7: uint256 constant LONG_FREEZE_CHARGES = 6; // 6 uses
9: uint48 constant MAX_SHORT_FREEZE = 2592000; // 1 month
9: uint48 constant MAX_SHORT_FREEZE = 2592000; // 1 month
10: uint48 constant MAX_LONG_FREEZE = 31536000; // 1 year
10: uint48 constant MAX_LONG_FREEZE = 31536000; // 1 year
38: uint48 public unfreezeAt; // {s} uint48.max to pause indefinitely
38: uint48 public unfreezeAt; // {s} uint48.max to pause indefinitely
39: uint48 public shortFreeze; // {s} length of an initial freeze
39: uint48 public shortFreeze; // {s} length of an initial freeze
40: uint48 public longFreeze; // {s} length of a freeze extension
40: uint48 public longFreeze; // {s} length of a freeze extension
127: freezeUntil(uint48(block.timestamp) + shortFreeze);
140: longFreezes[_msgSender()] -= 1; // reverts on underflow
140: longFreezes[_msgSender()] -= 1; // reverts on underflow
140: longFreezes[_msgSender()] -= 1; // reverts on underflow
144: freezeUntil(uint48(block.timestamp) + longFreeze);
File: contracts/mixins/ComponentRegistry.sol
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
6: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
7: import "../interfaces/IMain.sol";
7: import "../interfaces/IMain.sol";
8: import "./Auth.sol";
File: contracts/mixins/Versioned.sol
4: import "../interfaces/IVersioned.sol";
4: import "../interfaces/IVersioned.sol";
File: contracts/p1/AssetRegistry.sol
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
5: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
5: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
5: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
6: import "../interfaces/IAssetRegistry.sol";
6: import "../interfaces/IAssetRegistry.sol";
7: import "../interfaces/IMain.sol";
7: import "../interfaces/IMain.sol";
8: import "./mixins/Component.sol";
8: import "./mixins/Component.sol";
15: uint256 public constant GAS_TO_RESERVE = 900000; // just enough to disable basket on n=128
15: uint256 public constant GAS_TO_RESERVE = 900000; // just enough to disable basket on n=128
29: uint48 public lastRefresh; // {s}
29: uint48 public lastRefresh; // {s}
46: for (uint256 i = 0; i < length; ++i) {
46: for (uint256 i = 0; i < length; ++i) {
59: for (uint256 i = 0; i < length; ++i) {
59: for (uint256 i = 0; i < length; ++i) {
64: lastRefresh = uint48(block.timestamp); // safer to do this at end than start, actually
64: lastRefresh = uint48(block.timestamp); // safer to do this at end than start, actually
90: if (quantity > 0) basketHandler.disableBasket(); // not an interaction
90: if (quantity > 0) basketHandler.disableBasket(); // not an interaction
107: if (quantity > 0) basketHandler.disableBasket(); // not an interaction
107: if (quantity > 0) basketHandler.disableBasket(); // not an interaction
145: for (uint256 i = 0; i < length; ++i) {
145: for (uint256 i = 0; i < length; ++i) {
157: for (uint256 i = 0; i < length; ++i) {
157: for (uint256 i = 0; i < length; ++i) {
211: return gas - GAS_TO_RESERVE;
File: contracts/p1/BackingManager.sol
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6: import "../interfaces/IAsset.sol";
6: import "../interfaces/IAsset.sol";
7: import "../interfaces/IBackingManager.sol";
7: import "../interfaces/IBackingManager.sol";
8: import "../interfaces/IMain.sol";
8: import "../interfaces/IMain.sol";
9: import "../libraries/Array.sol";
9: import "../libraries/Array.sol";
10: import "../libraries/Fixed.sol";
10: import "../libraries/Fixed.sol";
11: import "./mixins/Trading.sol";
11: import "./mixins/Trading.sol";
12: import "./mixins/RecollateralizationLib.sol";
12: import "./mixins/RecollateralizationLib.sol";
33: uint48 public constant MAX_TRADING_DELAY = 31536000; // {s} 1 year
33: uint48 public constant MAX_TRADING_DELAY = 31536000; // {s} 1 year
34: uint192 public constant MAX_BACKING_BUFFER = FIX_ONE; // {1} 100%
34: uint192 public constant MAX_BACKING_BUFFER = FIX_ONE; // {1} 100%
36: uint48 public tradingDelay; // {s} how long to wait until resuming trading after switching
36: uint48 public tradingDelay; // {s} how long to wait until resuming trading after switching
37: uint192 public backingBuffer; // {1} how much extra backing collateral to keep
37: uint192 public backingBuffer; // {1} how much extra backing collateral to keep
41: mapping(TradeKind => uint48) private tradeEnd; // {s} last endTime() of an auction per kind
41: mapping(TradeKind => uint48) private tradeEnd; // {s} last endTime() of an auction per kind
84: trade = super.settleTrade(sell); // nonReentrant
84: trade = super.settleTrade(sell); // nonReentrant
94: if (errData.length == 0) revert(); // solhint-disable-line reason-string
94: if (errData.length == 0) revert(); // solhint-disable-line reason-string
94: if (errData.length == 0) revert(); // solhint-disable-line reason-string
94: if (errData.length == 0) revert(); // solhint-disable-line reason-string
94: if (errData.length == 0) revert(); // solhint-disable-line reason-string
112: _msgSender() == address(this) || tradeEnd[kind] + ONE_BLOCK < block.timestamp,
118: require(block.timestamp >= basketHandler.timestamp() + tradingDelay, "trading delayed");
127: if (balance >= MAX_DISTRIBUTION * MAX_DESTINATIONS) main.rToken().dissolve(balance);
128: if (basketsHeld.bottom >= rToken.basketsNeeded()) return; // return if now capitalized
128: if (basketsHeld.bottom >= rToken.basketsNeeded()) return; // return if now capitalized
151: if (req.sellAmount > bal) stRSR.seizeRSR(req.sellAmount - bal);
182: require(block.timestamp >= basketHandler.timestamp() + tradingDelay, "trading delayed");
212: uint192 needed = rToken.basketsNeeded().mul(FIX_ONE + backingBuffer); // {BU}
212: uint192 needed = rToken.basketsNeeded().mul(FIX_ONE + backingBuffer); // {BU}
212: uint192 needed = rToken.basketsNeeded().mul(FIX_ONE + backingBuffer); // {BU}
214: rToken.mint(basketsHeld.bottom - needed);
215: needed = rToken.basketsNeeded().mul(FIX_ONE + backingBuffer); // keep buffer
215: needed = rToken.basketsNeeded().mul(FIX_ONE + backingBuffer); // keep buffer
215: needed = rToken.basketsNeeded().mul(FIX_ONE + backingBuffer); // keep buffer
226: for (uint256 i = 0; i < length; ++i) {
226: for (uint256 i = 0; i < length; ++i) {
236: uint256 tokensPerShare = delta / (totals.rTokenTotal + totals.rsrTotal);
236: uint256 tokensPerShare = delta / (totals.rTokenTotal + totals.rsrTotal);
242: erc20s[i].safeTransfer(address(rsrTrader), tokensPerShare * totals.rsrTotal);
247: tokensPerShare * totals.rTokenTotal
File: contracts/p1/BasketHandler.sol
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6: import "@openzeppelin/contracts/utils/structs/EnumerableMap.sol";
6: import "@openzeppelin/contracts/utils/structs/EnumerableMap.sol";
6: import "@openzeppelin/contracts/utils/structs/EnumerableMap.sol";
6: import "@openzeppelin/contracts/utils/structs/EnumerableMap.sol";
7: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
7: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
7: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
7: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
8: import "../interfaces/IAssetRegistry.sol";
8: import "../interfaces/IAssetRegistry.sol";
9: import "../interfaces/IBasketHandler.sol";
9: import "../interfaces/IBasketHandler.sol";
10: import "../interfaces/IMain.sol";
10: import "../interfaces/IMain.sol";
11: import "../libraries/Array.sol";
11: import "../libraries/Array.sol";
12: import "../libraries/Fixed.sol";
12: import "../libraries/Fixed.sol";
13: import "./mixins/BasketLib.sol";
13: import "./mixins/BasketLib.sol";
14: import "./mixins/Component.sol";
14: import "./mixins/Component.sol";
27: uint192 public constant MAX_TARGET_AMT = 1e3 * FIX_ONE; // {target/BU} max basket weight
27: uint192 public constant MAX_TARGET_AMT = 1e3 * FIX_ONE; // {target/BU} max basket weight
27: uint192 public constant MAX_TARGET_AMT = 1e3 * FIX_ONE; // {target/BU} max basket weight
27: uint192 public constant MAX_TARGET_AMT = 1e3 * FIX_ONE; // {target/BU} max basket weight
28: uint48 public constant MIN_WARMUP_PERIOD = 60; // {s} 1 minute
28: uint48 public constant MIN_WARMUP_PERIOD = 60; // {s} 1 minute
29: uint48 public constant MAX_WARMUP_PERIOD = 31536000; // {s} 1 year
29: uint48 public constant MAX_WARMUP_PERIOD = 31536000; // {s} 1 year
46: uint48 public nonce; // {basketNonce} A unique identifier for this basket instance
46: uint48 public nonce; // {basketNonce} A unique identifier for this basket instance
47: uint48 public timestamp; // The timestamp when this basket was last set
47: uint48 public timestamp; // The timestamp when this basket was last set
64: uint48 public warmupPeriod; // {s} how long to wait until issuance/trading after regaining SOUND
64: uint48 public warmupPeriod; // {s} how long to wait until issuance/trading after regaining SOUND
64: uint48 public warmupPeriod; // {s} how long to wait until issuance/trading after regaining SOUND
78: EnumerableMap.Bytes32ToUintMap private _targetAmts; // targetName -> {target/BU}
78: EnumerableMap.Bytes32ToUintMap private _targetAmts; // targetName -> {target/BU}
78: EnumerableMap.Bytes32ToUintMap private _targetAmts; // targetName -> {target/BU}
78: EnumerableMap.Bytes32ToUintMap private _targetAmts; // targetName -> {target/BU}
119: for (uint256 i = 0; i < len; ++i) refAmts[i] = basket.refAmts[basket.erc20s[i]];
119: for (uint256 i = 0; i < len; ++i) refAmts[i] = basket.refAmts[basket.erc20s[i]];
185: for (uint256 i = 0; i < config.erc20s.length; ++i) {
185: for (uint256 i = 0; i < config.erc20s.length; ++i) {
194: for (uint256 i = 0; i < erc20s.length; ++i) {
194: for (uint256 i = 0; i < erc20s.length; ++i) {
229: for (uint256 i = 0; i < erc20s.length; ++i) {
229: for (uint256 i = 0; i < erc20s.length; ++i) {
254: for (uint256 i = 0; i < size; ++i) {
254: for (uint256 i = 0; i < size; ++i) {
264: (block.timestamp >= lastStatusTimestamp + warmupPeriod);
331: for (uint256 i = 0; i < len; ++i) {
331: for (uint256 i = 0; i < len; ++i) {
339: low256 += qty.safeMul(lowP, RoundingMode.FLOOR);
340: high256 += qty.safeMul(highP, RoundingMode.CEIL);
363: for (uint256 i = 0; i < length; ++i) {
363: for (uint256 i = 0; i < length; ++i) {
394: uint256 len; // length of return arrays
394: uint256 len; // length of return arrays
397: for (uint48 i = 0; i < basketNonces.length; ++i) {
397: for (uint48 i = 0; i < basketNonces.length; ++i) {
402: for (uint256 j = 0; j < b.erc20s.length; ++j) {
402: for (uint256 j = 0; j < b.erc20s.length; ++j) {
408: for (uint256 k = 0; k < len; ++k) {
408: for (uint256 k = 0; k < len; ++k) {
422: ++len;
422: ++len;
425: refAmtsAll[erc20Index] += amt;
434: for (uint256 i = 0; i < len; ++i) {
434: for (uint256 i = 0; i < len; ++i) {
438: if (!asset.isCollateral()) continue; // skip token if no longer registered
438: if (!asset.isCollateral()) continue; // skip token if no longer registered
452: if (errData.length == 0) revert(); // solhint-disable-line reason-string
452: if (errData.length == 0) revert(); // solhint-disable-line reason-string
452: if (errData.length == 0) revert(); // solhint-disable-line reason-string
452: if (errData.length == 0) revert(); // solhint-disable-line reason-string
452: if (errData.length == 0) revert(); // solhint-disable-line reason-string
469: for (uint256 i = 0; i < length; ++i) {
469: for (uint256 i = 0; i < length; ++i) {
513: nonce += 1;
523: for (uint256 i = 0; i < len; ++i) {
523: for (uint256 i = 0; i < len; ++i) {
542: for (uint256 i = 0; i < len; ++i) {
542: for (uint256 i = 0; i < len; ++i) {
548: contains ? amt + config.targetAmts[erc20] : config.targetAmts[erc20]
554: for (uint256 i = 0; i < len; ++i) {
554: for (uint256 i = 0; i < len; ++i) {
558: if (amt > newTargetAmts[i]) _targetAmts.set(targetName, amt - newTargetAmts[i]);
568: for (uint256 i = 0; i < erc20s.length; i++) {
568: for (uint256 i = 0; i < erc20s.length; i++) {
594: for (uint256 i = 0; i < b.erc20s.length; ++i) {
594: for (uint256 i = 0; i < b.erc20s.length; ++i) {
598: if (!asset.isCollateral()) continue; // skip token if no longer registered
598: if (!asset.isCollateral()) continue; // skip token if no longer registered
610: if (errData.length == 0) revert(); // solhint-disable-line reason-string
610: if (errData.length == 0) revert(); // solhint-disable-line reason-string
610: if (errData.length == 0) revert(); // solhint-disable-line reason-string
610: if (errData.length == 0) revert(); // solhint-disable-line reason-string
610: if (errData.length == 0) revert(); // solhint-disable-line reason-string
633: for (uint256 i = 0; i < erc20s.length; ++i) {
633: for (uint256 i = 0; i < erc20s.length; ++i) {
651: for (uint256 i = 0; i < erc20s.length; ++i) {
651: for (uint256 i = 0; i < erc20s.length; ++i) {
File: contracts/p1/Broker.sol
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
5: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
5: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
5: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
6: import "@openzeppelin/contracts/proxy/Clones.sol";
6: import "@openzeppelin/contracts/proxy/Clones.sol";
6: import "@openzeppelin/contracts/proxy/Clones.sol";
7: import "../interfaces/IBroker.sol";
7: import "../interfaces/IBroker.sol";
8: import "../interfaces/IMain.sol";
8: import "../interfaces/IMain.sol";
9: import "../interfaces/ITrade.sol";
9: import "../interfaces/ITrade.sol";
10: import "../libraries/Fixed.sol";
10: import "../libraries/Fixed.sol";
11: import "./mixins/Component.sol";
11: import "./mixins/Component.sol";
12: import "../plugins/trading/DutchTrade.sol";
12: import "../plugins/trading/DutchTrade.sol";
12: import "../plugins/trading/DutchTrade.sol";
13: import "../plugins/trading/GnosisTrade.sol";
13: import "../plugins/trading/GnosisTrade.sol";
13: import "../plugins/trading/GnosisTrade.sol";
25: uint48 public constant MAX_AUCTION_LENGTH = 604800; // {s} max valid duration - 1 week
25: uint48 public constant MAX_AUCTION_LENGTH = 604800; // {s} max valid duration - 1 week
25: uint48 public constant MAX_AUCTION_LENGTH = 604800; // {s} max valid duration - 1 week
26: uint48 public constant MIN_AUCTION_LENGTH = ONE_BLOCK * 2; // {s} min auction length - 2 blocks
26: uint48 public constant MIN_AUCTION_LENGTH = ONE_BLOCK * 2; // {s} min auction length - 2 blocks
26: uint48 public constant MIN_AUCTION_LENGTH = ONE_BLOCK * 2; // {s} min auction length - 2 blocks
26: uint48 public constant MIN_AUCTION_LENGTH = ONE_BLOCK * 2; // {s} min auction length - 2 blocks
File: contracts/p1/Deployer.sol
4: import "@openzeppelin/contracts/proxy/Clones.sol";
4: import "@openzeppelin/contracts/proxy/Clones.sol";
4: import "@openzeppelin/contracts/proxy/Clones.sol";
5: import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
5: import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
5: import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
5: import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
6: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
6: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
6: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
6: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
6: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
7: import "../interfaces/IAsset.sol";
7: import "../interfaces/IAsset.sol";
8: import "../interfaces/IAssetRegistry.sol";
8: import "../interfaces/IAssetRegistry.sol";
9: import "../interfaces/IBackingManager.sol";
9: import "../interfaces/IBackingManager.sol";
10: import "../interfaces/IBasketHandler.sol";
10: import "../interfaces/IBasketHandler.sol";
11: import "../interfaces/IBroker.sol";
11: import "../interfaces/IBroker.sol";
12: import "../interfaces/IDeployer.sol";
12: import "../interfaces/IDeployer.sol";
13: import "../interfaces/IDistributor.sol";
13: import "../interfaces/IDistributor.sol";
14: import "../interfaces/IFurnace.sol";
14: import "../interfaces/IFurnace.sol";
15: import "../interfaces/IRevenueTrader.sol";
15: import "../interfaces/IRevenueTrader.sol";
16: import "../interfaces/IRToken.sol";
16: import "../interfaces/IRToken.sol";
17: import "../interfaces/IStRSR.sol";
17: import "../interfaces/IStRSR.sol";
18: import "../mixins/Versioned.sol";
18: import "../mixins/Versioned.sol";
19: import "../plugins/assets/Asset.sol";
19: import "../plugins/assets/Asset.sol";
19: import "../plugins/assets/Asset.sol";
20: import "../plugins/assets/RTokenAsset.sol";
20: import "../plugins/assets/RTokenAsset.sol";
20: import "../plugins/assets/RTokenAsset.sol";
21: import "./Main.sol";
22: import "../libraries/String.sol";
22: import "../libraries/String.sol";
File: contracts/p1/Distributor.sol
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
6: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
6: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
6: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
7: import "../interfaces/IDistributor.sol";
7: import "../interfaces/IDistributor.sol";
8: import "../interfaces/IMain.sol";
8: import "../interfaces/IMain.sol";
9: import "../libraries/Fixed.sol";
9: import "../libraries/Fixed.sol";
10: import "./mixins/Component.sol";
10: import "./mixins/Component.sol";
34: uint8 public constant MAX_DESTINATIONS_ALLOWED = MAX_DESTINATIONS; // 100
34: uint8 public constant MAX_DESTINATIONS_ALLOWED = MAX_DESTINATIONS; // 100
89: bool isRSR = erc20 == rsr; // if false: isRToken
89: bool isRSR = erc20 == rsr; // if false: isRToken
95: tokensPerShare = amount / totalShares;
104: for (uint256 i = 0; i < destinations.length(); ++i) {
104: for (uint256 i = 0; i < destinations.length(); ++i) {
111: uint256 transferAmt = tokensPerShare * numberOfShares;
124: numTransfers++;
124: numTransfers++;
129: for (uint256 i = 0; i < numTransfers; i++) {
129: for (uint256 i = 0; i < numTransfers; i++) {
139: for (uint256 i = 0; i < length; ++i) {
139: for (uint256 i = 0; i < length; ++i) {
141: revTotals.rTokenTotal += share.rTokenDist;
142: revTotals.rsrTotal += share.rsrDist;
File: contracts/p1/Furnace.sol
4: import "../libraries/Fixed.sol";
4: import "../libraries/Fixed.sol";
5: import "../interfaces/IFurnace.sol";
5: import "../interfaces/IFurnace.sol";
6: import "./mixins/Component.sol";
6: import "./mixins/Component.sol";
15: uint192 public constant MAX_RATIO = FIX_ONE; // {1} 100%
15: uint192 public constant MAX_RATIO = FIX_ONE; // {1} 100%
16: uint48 public constant PERIOD = ONE_BLOCK; // {s} 12 seconds; 1 block on PoS Ethereum
16: uint48 public constant PERIOD = ONE_BLOCK; // {s} 12 seconds; 1 block on PoS Ethereum
21: uint192 public ratio; // {1} What fraction of balance to melt each period
21: uint192 public ratio; // {1} What fraction of balance to melt each period
24: uint48 public lastPayout; // {seconds} The last time we did a payout
24: uint48 public lastPayout; // {seconds} The last time we did a payout
25: uint256 public lastPayoutBal; // {qRTok} The balance of RToken at the last payout
25: uint256 public lastPayoutBal; // {qRTok} The balance of RToken at the last payout
67: if (uint48(block.timestamp) < uint64(lastPayout) + PERIOD) return;
70: uint48 numPeriods = uint48((block.timestamp) - lastPayout) / PERIOD;
70: uint48 numPeriods = uint48((block.timestamp) - lastPayout) / PERIOD;
77: lastPayout += numPeriods * PERIOD;
77: lastPayout += numPeriods * PERIOD;
78: lastPayoutBal = rToken.balanceOf(address(this)) - amount;
File: contracts/p1/Main.sol
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
7: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
7: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
7: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
7: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
8: import "../interfaces/IMain.sol";
8: import "../interfaces/IMain.sol";
9: import "../mixins/ComponentRegistry.sol";
9: import "../mixins/ComponentRegistry.sol";
10: import "../mixins/Auth.sol";
10: import "../mixins/Auth.sol";
11: import "../mixins/Versioned.sol";
11: import "../mixins/Versioned.sol";
File: contracts/p1/RToken.sol
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
6: import "../interfaces/IMain.sol";
6: import "../interfaces/IMain.sol";
7: import "../interfaces/IRToken.sol";
7: import "../interfaces/IRToken.sol";
8: import "../libraries/Fixed.sol";
8: import "../libraries/Fixed.sol";
9: import "../libraries/Throttle.sol";
9: import "../libraries/Throttle.sol";
10: import "../vendor/ERC20PermitUpgradeable.sol";
10: import "../vendor/ERC20PermitUpgradeable.sol";
11: import "./mixins/Component.sol";
11: import "./mixins/Component.sol";
22: uint256 public constant MIN_THROTTLE_RATE_AMT = 1e18; // {qRTok}
22: uint256 public constant MIN_THROTTLE_RATE_AMT = 1e18; // {qRTok}
23: uint256 public constant MAX_THROTTLE_RATE_AMT = 1e48; // {qRTok}
23: uint256 public constant MAX_THROTTLE_RATE_AMT = 1e48; // {qRTok}
24: uint192 public constant MAX_THROTTLE_PCT_AMT = 1e18; // {qRTok}
24: uint192 public constant MAX_THROTTLE_PCT_AMT = 1e18; // {qRTok}
25: uint192 public constant MIN_EXCHANGE_RATE = 1e9; // D18{BU/rTok}
25: uint192 public constant MIN_EXCHANGE_RATE = 1e9; // D18{BU/rTok}
25: uint192 public constant MIN_EXCHANGE_RATE = 1e9; // D18{BU/rTok}
26: uint192 public constant MAX_EXCHANGE_RATE = 1e27; // D18{BU/rTok}
26: uint192 public constant MAX_EXCHANGE_RATE = 1e27; // D18{BU/rTok}
26: uint192 public constant MAX_EXCHANGE_RATE = 1e27; // D18{BU/rTok}
55: uint192 public basketsNeeded; // D18{BU}
55: uint192 public basketsNeeded; // D18{BU}
110: address issuer = _msgSender(); // OK to save: it can't be changed in reentrant runs
110: address issuer = _msgSender(); // OK to save: it can't be changed in reentrant runs
119: issuanceThrottle.useAvailable(supply, int256(amount)); // reverts on over-issuance
119: issuanceThrottle.useAvailable(supply, int256(amount)); // reverts on over-issuance
119: issuanceThrottle.useAvailable(supply, int256(amount)); // reverts on over-issuance
120: redemptionThrottle.useAvailable(supply, -int256(amount)); // shouldn't revert
120: redemptionThrottle.useAvailable(supply, -int256(amount)); // shouldn't revert
120: redemptionThrottle.useAvailable(supply, -int256(amount)); // shouldn't revert
144: for (uint256 i = 0; i < erc20s.length; ++i) {
144: for (uint256 i = 0; i < erc20s.length; ++i) {
184: try main.furnace().melt() {} catch {} // nice for the redeemer, but not necessary
184: try main.furnace().melt() {} catch {} // nice for the redeemer, but not necessary
196: issuanceThrottle.useAvailable(supply, -int256(amount));
197: redemptionThrottle.useAvailable(supply, int256(amount)); // reverts on over-redemption
197: redemptionThrottle.useAvailable(supply, int256(amount)); // reverts on over-redemption
197: redemptionThrottle.useAvailable(supply, int256(amount)); // reverts on over-redemption
207: for (uint256 i = 0; i < erc20s.length; ++i) {
207: for (uint256 i = 0; i < erc20s.length; ++i) {
264: for (uint256 i = 0; i < portions.length; ++i) {
264: for (uint256 i = 0; i < portions.length; ++i) {
265: portionsSum += portions[i];
272: issuanceThrottle.useAvailable(supply, -int256(amount));
273: redemptionThrottle.useAvailable(supply, int256(amount)); // reverts on over-redemption
273: redemptionThrottle.useAvailable(supply, int256(amount)); // reverts on over-redemption
273: redemptionThrottle.useAvailable(supply, int256(amount)); // reverts on over-redemption
292: for (uint256 i = 0; i < erc20sOut.length; ++i) {
292: for (uint256 i = 0; i < erc20sOut.length; ++i) {
298: ); // FLOOR
298: ); // FLOOR
306: for (uint256 i = 0; i < expectedERC20sOut.length; ++i) {
306: for (uint256 i = 0; i < expectedERC20sOut.length; ++i) {
316: for (uint256 i = 0; i < erc20sOut.length; ++i) {
316: for (uint256 i = 0; i < erc20sOut.length; ++i) {
317: if (amountsOut[i] == 0) continue; // unregistered ERC20s will have 0 amount
317: if (amountsOut[i] == 0) continue; // unregistered ERC20s will have 0 amount
333: for (uint256 i = 0; i < expectedERC20sOut.length; ++i) {
333: for (uint256 i = 0; i < expectedERC20sOut.length; ++i) {
336: require(bal - pastBals[i] >= minAmounts[i], "redemption below minimum");
401: uint256 low = (FIX_ONE_256 * basketsNeeded) / supply; // D18{BU/rTok}
401: uint256 low = (FIX_ONE_256 * basketsNeeded) / supply; // D18{BU/rTok}
401: uint256 low = (FIX_ONE_256 * basketsNeeded) / supply; // D18{BU/rTok}
401: uint256 low = (FIX_ONE_256 * basketsNeeded) / supply; // D18{BU/rTok}
401: uint256 low = (FIX_ONE_256 * basketsNeeded) / supply; // D18{BU/rTok}
402: uint256 high = (FIX_ONE_256 * basketsNeeded + (supply - 1)) / supply; // D18{BU/rTok}
402: uint256 high = (FIX_ONE_256 * basketsNeeded + (supply - 1)) / supply; // D18{BU/rTok}
402: uint256 high = (FIX_ONE_256 * basketsNeeded + (supply - 1)) / supply; // D18{BU/rTok}
402: uint256 high = (FIX_ONE_256 * basketsNeeded + (supply - 1)) / supply; // D18{BU/rTok}
402: uint256 high = (FIX_ONE_256 * basketsNeeded + (supply - 1)) / supply; // D18{BU/rTok}
402: uint256 high = (FIX_ONE_256 * basketsNeeded + (supply - 1)) / supply; // D18{BU/rTok}
402: uint256 high = (FIX_ONE_256 * basketsNeeded + (supply - 1)) / supply; // D18{BU/rTok}
479: ? amtBaskets.muluDivu(totalSupply, basketsNeeded) // {rTok} = {BU} * {qRTok} * {qRTok}
479: ? amtBaskets.muluDivu(totalSupply, basketsNeeded) // {rTok} = {BU} * {qRTok} * {qRTok}
479: ? amtBaskets.muluDivu(totalSupply, basketsNeeded) // {rTok} = {BU} * {qRTok} * {qRTok}
479: ? amtBaskets.muluDivu(totalSupply, basketsNeeded) // {rTok} = {BU} * {qRTok} * {qRTok}
480: : amtBaskets; // {rTok}
480: : amtBaskets; // {rTok}
481: emit BasketsNeededChanged(basketsNeeded, basketsNeeded + amtBaskets);
482: basketsNeeded += amtBaskets;
499: amtBaskets = basketsNeeded.muluDivu(amtRToken, totalSupply()); // FLOOR
499: amtBaskets = basketsNeeded.muluDivu(amtRToken, totalSupply()); // FLOOR
500: emit BasketsNeededChanged(basketsNeeded, basketsNeeded - amtBaskets);
501: basketsNeeded -= amtBaskets;
File: contracts/p1/RevenueTrader.sol
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6: import "../interfaces/IMain.sol";
6: import "../interfaces/IMain.sol";
7: import "../interfaces/IAssetRegistry.sol";
7: import "../interfaces/IAssetRegistry.sol";
8: import "./mixins/Trading.sol";
8: import "./mixins/Trading.sol";
9: import "./mixins/TradeLib.sol";
9: import "./mixins/TradeLib.sol";
49: trade = super.settleTrade(sell); // nonReentrant
49: trade = super.settleTrade(sell); // nonReentrant
114: (uint192 sellPrice, ) = sell.price(); // {UoA/tok}
114: (uint192 sellPrice, ) = sell.price(); // {UoA/tok}
114: (uint192 sellPrice, ) = sell.price(); // {UoA/tok}
115: (, uint192 buyPrice) = buy.price(); // {UoA/tok}
115: (, uint192 buyPrice) = buy.price(); // {UoA/tok}
115: (, uint192 buyPrice) = buy.price(); // {UoA/tok}
File: contracts/p1/StRSR.sol
4: import "@openzeppelin/contracts-upgradeable/interfaces/IERC1271Upgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/interfaces/IERC1271Upgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/interfaces/IERC1271Upgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/interfaces/IERC1271Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/utils/cryptography/SignatureCheckerUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/utils/cryptography/SignatureCheckerUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/utils/cryptography/SignatureCheckerUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/utils/cryptography/SignatureCheckerUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/utils/cryptography/SignatureCheckerUpgradeable.sol";
7: import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol";
7: import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol";
7: import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol";
7: import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol";
7: import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol";
7: import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol";
8: import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
8: import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
8: import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
8: import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
9: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
9: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
9: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
9: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
11: import "../interfaces/IStRSR.sol";
11: import "../interfaces/IStRSR.sol";
12: import "../interfaces/IMain.sol";
12: import "../interfaces/IMain.sol";
13: import "../libraries/Fixed.sol";
13: import "../libraries/Fixed.sol";
14: import "../libraries/Permit.sol";
14: import "../libraries/Permit.sol";
15: import "./mixins/Component.sol";
15: import "./mixins/Component.sol";
37: uint48 public constant PERIOD = ONE_BLOCK; // {s} 12 seconds; 1 block on PoS Ethereum
37: uint48 public constant PERIOD = ONE_BLOCK; // {s} 12 seconds; 1 block on PoS Ethereum
38: uint48 public constant MIN_UNSTAKING_DELAY = PERIOD * 2; // {s}
38: uint48 public constant MIN_UNSTAKING_DELAY = PERIOD * 2; // {s}
38: uint48 public constant MIN_UNSTAKING_DELAY = PERIOD * 2; // {s}
39: uint48 public constant MAX_UNSTAKING_DELAY = 31536000; // {s} 1 year
39: uint48 public constant MAX_UNSTAKING_DELAY = 31536000; // {s} 1 year
40: uint192 public constant MAX_REWARD_RATIO = FIX_ONE; // {1} 100%
40: uint192 public constant MAX_REWARD_RATIO = FIX_ONE; // {1} 100%
43: string public name; // immutable
43: string public name; // immutable
44: string public symbol; // immutable
44: string public symbol; // immutable
61: mapping(uint256 => mapping(address => uint256)) private stakes; // Stakes per account {qStRSR}
61: mapping(uint256 => mapping(address => uint256)) private stakes; // Stakes per account {qStRSR}
62: uint256 private totalStakes; // Total of all stakes {qStRSR}
62: uint256 private totalStakes; // Total of all stakes {qStRSR}
63: uint256 private stakeRSR; // Amount of RSR backing all stakes {qRSR}
63: uint256 private stakeRSR; // Amount of RSR backing all stakes {qRSR}
64: uint192 private stakeRate; // The exchange rate between stakes and RSR. D18{qStRSR/qRSR}
64: uint192 private stakeRate; // The exchange rate between stakes and RSR. D18{qStRSR/qRSR}
64: uint192 private stakeRate; // The exchange rate between stakes and RSR. D18{qStRSR/qRSR}
66: uint192 private constant MAX_STAKE_RATE = 1e9 * FIX_ONE; // 1e9 D18{qStRSR/qRSR}
66: uint192 private constant MAX_STAKE_RATE = 1e9 * FIX_ONE; // 1e9 D18{qStRSR/qRSR}
66: uint192 private constant MAX_STAKE_RATE = 1e9 * FIX_ONE; // 1e9 D18{qStRSR/qRSR}
66: uint192 private constant MAX_STAKE_RATE = 1e9 * FIX_ONE; // 1e9 D18{qStRSR/qRSR}
78: uint176 drafts; // Total amount of drafts that will become available // {qDrafts}
78: uint176 drafts; // Total amount of drafts that will become available // {qDrafts}
78: uint176 drafts; // Total amount of drafts that will become available // {qDrafts}
78: uint176 drafts; // Total amount of drafts that will become available // {qDrafts}
79: uint64 availableAt; // When the last of the drafts will become available
79: uint64 availableAt; // When the last of the drafts will become available
82: mapping(uint256 => mapping(address => CumulativeDraft[])) public draftQueues; // {drafts}
82: mapping(uint256 => mapping(address => CumulativeDraft[])) public draftQueues; // {drafts}
83: mapping(uint256 => mapping(address => uint256)) public firstRemainingDraft; // draft index
83: mapping(uint256 => mapping(address => uint256)) public firstRemainingDraft; // draft index
84: uint256 private totalDrafts; // Total of all drafts {qDrafts}
84: uint256 private totalDrafts; // Total of all drafts {qDrafts}
85: uint256 private draftRSR; // Amount of RSR backing all drafts {qRSR}
85: uint256 private draftRSR; // Amount of RSR backing all drafts {qRSR}
86: uint192 public draftRate; // The exchange rate between drafts and RSR. D18{qDrafts/qRSR}
86: uint192 public draftRate; // The exchange rate between drafts and RSR. D18{qDrafts/qRSR}
86: uint192 public draftRate; // The exchange rate between drafts and RSR. D18{qDrafts/qRSR}
88: uint192 private constant MAX_DRAFT_RATE = 1e9 * FIX_ONE; // 1e9 D18{qDrafts/qRSR}
88: uint192 private constant MAX_DRAFT_RATE = 1e9 * FIX_ONE; // 1e9 D18{qDrafts/qRSR}
88: uint192 private constant MAX_DRAFT_RATE = 1e9 * FIX_ONE; // 1e9 D18{qDrafts/qRSR}
88: uint192 private constant MAX_DRAFT_RATE = 1e9 * FIX_ONE; // 1e9 D18{qDrafts/qRSR}
136: uint48 public unstakingDelay; // {s} The minimum length of time spent in the draft queue
136: uint48 public unstakingDelay; // {s} The minimum length of time spent in the draft queue
137: uint192 public rewardRatio; // {1} The fraction of the revenue balance to handout per period
137: uint192 public rewardRatio; // {1} The fraction of the revenue balance to handout per period
155: uint192 private constant MAX_WITHDRAWAL_LEAK = 3e17; // {1} 30%
155: uint192 private constant MAX_WITHDRAWAL_LEAK = 3e17; // {1} 30%
157: uint192 private leaked; // {1} stake fraction that has withdrawn without a refresh
157: uint192 private leaked; // {1} stake fraction that has withdrawn without a refresh
158: uint48 private lastWithdrawRefresh; // {s} timestamp of last refresh() during withdraw()
158: uint48 private lastWithdrawRefresh; // {s} timestamp of last refresh() during withdraw()
159: uint192 public withdrawalLeak; // {1} gov param -- % RSR that can be withdrawn without refresh
159: uint192 public withdrawalLeak; // {1} gov param -- % RSR that can be withdrawn without refresh
159: uint192 public withdrawalLeak; // {1} gov param -- % RSR that can be withdrawn without refresh
159: uint192 public withdrawalLeak; // {1} gov param -- % RSR that can be withdrawn without refresh
268: uint256 newStakeRSR = (FIX_ONE_256 * totalStakes + (stakeRate - 1)) / stakeRate;
268: uint256 newStakeRSR = (FIX_ONE_256 * totalStakes + (stakeRate - 1)) / stakeRate;
268: uint256 newStakeRSR = (FIX_ONE_256 * totalStakes + (stakeRate - 1)) / stakeRate;
268: uint256 newStakeRSR = (FIX_ONE_256 * totalStakes + (stakeRate - 1)) / stakeRate;
269: uint256 rsrAmount = stakeRSR - newStakeRSR;
306: require(endId <= queue.length, "index out-of-bounds");
306: require(endId <= queue.length, "index out-of-bounds");
307: require(queue[endId - 1].availableAt <= block.timestamp, "withdrawal unavailable");
311: uint192 oldDrafts = firstId > 0 ? queue[firstId - 1].drafts : 0;
312: uint192 draftAmount = queue[endId - 1].drafts - oldDrafts;
312: uint192 draftAmount = queue[endId - 1].drafts - oldDrafts;
318: uint256 newTotalDrafts = totalDrafts - draftAmount;
320: uint256 newDraftRSR = (newTotalDrafts * FIX_ONE_256 + (draftRate - 1)) / draftRate;
320: uint256 newDraftRSR = (newTotalDrafts * FIX_ONE_256 + (draftRate - 1)) / draftRate;
320: uint256 newDraftRSR = (newTotalDrafts * FIX_ONE_256 + (draftRate - 1)) / draftRate;
320: uint256 newDraftRSR = (newTotalDrafts * FIX_ONE_256 + (draftRate - 1)) / draftRate;
321: uint256 rsrAmount = draftRSR - newDraftRSR;
353: require(endId <= queue.length, "index out-of-bounds");
353: require(endId <= queue.length, "index out-of-bounds");
358: uint192 oldDrafts = firstId > 0 ? queue[firstId - 1].drafts : 0;
359: uint192 draftAmount = queue[endId - 1].drafts - oldDrafts;
359: uint192 draftAmount = queue[endId - 1].drafts - oldDrafts;
365: uint256 newTotalDrafts = totalDrafts - draftAmount;
367: uint256 newDraftRSR = (newTotalDrafts * FIX_ONE_256 + (draftRate - 1)) / draftRate;
367: uint256 newDraftRSR = (newTotalDrafts * FIX_ONE_256 + (draftRate - 1)) / draftRate;
367: uint256 newDraftRSR = (newTotalDrafts * FIX_ONE_256 + (draftRate - 1)) / draftRate;
367: uint256 newDraftRSR = (newTotalDrafts * FIX_ONE_256 + (draftRate - 1)) / draftRate;
368: uint256 rsrAmount = draftRSR - newDraftRSR;
432: uint256 stakeRSRToTake = (stakeRSR * rsrAmount + (rsrBalance - 1)) / rsrBalance;
432: uint256 stakeRSRToTake = (stakeRSR * rsrAmount + (rsrBalance - 1)) / rsrBalance;
432: uint256 stakeRSRToTake = (stakeRSR * rsrAmount + (rsrBalance - 1)) / rsrBalance;
432: uint256 stakeRSRToTake = (stakeRSR * rsrAmount + (rsrBalance - 1)) / rsrBalance;
433: stakeRSR -= stakeRSRToTake;
439: stakeRate = uint192((FIX_ONE_256 * totalStakes + (stakeRSR - 1)) / stakeRSR);
439: stakeRate = uint192((FIX_ONE_256 * totalStakes + (stakeRSR - 1)) / stakeRSR);
439: stakeRate = uint192((FIX_ONE_256 * totalStakes + (stakeRSR - 1)) / stakeRSR);
439: stakeRate = uint192((FIX_ONE_256 * totalStakes + (stakeRSR - 1)) / stakeRSR);
442: seizedRSR += stakeRSR;
447: uint256 draftRSRToTake = (draftRSR * rsrAmount + (rsrBalance - 1)) / rsrBalance;
447: uint256 draftRSRToTake = (draftRSR * rsrAmount + (rsrBalance - 1)) / rsrBalance;
447: uint256 draftRSRToTake = (draftRSR * rsrAmount + (rsrBalance - 1)) / rsrBalance;
447: uint256 draftRSRToTake = (draftRSR * rsrAmount + (rsrBalance - 1)) / rsrBalance;
448: draftRSR -= draftRSRToTake;
449: seizedRSR += draftRSRToTake;
454: draftRate = uint192((FIX_ONE_256 * totalDrafts + (draftRSR - 1)) / draftRSR);
454: draftRate = uint192((FIX_ONE_256 * totalDrafts + (draftRSR - 1)) / draftRSR);
454: draftRate = uint192((FIX_ONE_256 * totalDrafts + (draftRSR - 1)) / draftRSR);
454: draftRate = uint192((FIX_ONE_256 * totalDrafts + (draftRSR - 1)) / draftRSR);
458: seizedRSR += draftRSR;
463: seizedRSR += (rewards * rsrAmount + (rsrBalance - 1)) / rsrBalance;
463: seizedRSR += (rewards * rsrAmount + (rsrBalance - 1)) / rsrBalance;
463: seizedRSR += (rewards * rsrAmount + (rsrBalance - 1)) / rsrBalance;
463: seizedRSR += (rewards * rsrAmount + (rsrBalance - 1)) / rsrBalance;
463: seizedRSR += (rewards * rsrAmount + (rsrBalance - 1)) / rsrBalance;
464: rsrRewardsAtLastPayout = rsrRewards() - seizedRSR;
474: return (FIX_SCALE_SQ + (stakeRate / 2)) / stakeRate; // ROUND method
474: return (FIX_SCALE_SQ + (stakeRate / 2)) / stakeRate; // ROUND method
474: return (FIX_SCALE_SQ + (stakeRate / 2)) / stakeRate; // ROUND method
474: return (FIX_SCALE_SQ + (stakeRate / 2)) / stakeRate; // ROUND method
474: return (FIX_SCALE_SQ + (stakeRate / 2)) / stakeRate; // ROUND method
496: while (left < right - 1) {
500: test = (left + right) / 2; // left < test < right because left < right - 1
500: test = (left + right) / 2; // left < test < right because left < right - 1
500: test = (left + right) / 2; // left < test < right because left < right - 1
500: test = (left + right) / 2; // left < test < right because left < right - 1
500: test = (left + right) / 2; // left < test < right because left < right - 1
559: if (block.timestamp < payoutLastPaid + PERIOD) return;
560: uint48 numPeriods = (uint48(block.timestamp) - payoutLastPaid) / PERIOD;
560: uint48 numPeriods = (uint48(block.timestamp) - payoutLastPaid) / PERIOD;
571: uint192 payoutRatio = FIX_ONE - FixLib.powu(FIX_ONE - rewardRatio, numPeriods);
571: uint192 payoutRatio = FIX_ONE - FixLib.powu(FIX_ONE - rewardRatio, numPeriods);
574: payout = (payoutRatio * rsrRewardsAtLastPayout) / FIX_ONE;
574: payout = (payoutRatio * rsrRewardsAtLastPayout) / FIX_ONE;
575: stakeRSR += payout;
578: payoutLastPaid += numPeriods * PERIOD;
578: payoutLastPaid += numPeriods * PERIOD;
588: : uint192((totalStakes * FIX_ONE_256 + (stakeRSR - 1)) / stakeRSR);
588: : uint192((totalStakes * FIX_ONE_256 + (stakeRSR - 1)) / stakeRSR);
588: : uint192((totalStakes * FIX_ONE_256 + (stakeRSR - 1)) / stakeRSR);
588: : uint192((totalStakes * FIX_ONE_256 + (stakeRSR - 1)) / stakeRSR);
611: draftRSR += rsrAmount;
613: uint256 newTotalDrafts = (draftRate * draftRSR) / FIX_ONE;
613: uint256 newTotalDrafts = (draftRate * draftRSR) / FIX_ONE;
614: uint256 draftAmount = newTotalDrafts - totalDrafts;
621: uint192 oldDrafts = index > 0 ? queue[index - 1].drafts : 0;
622: uint64 lastAvailableAt = index > 0 ? queue[index - 1].availableAt : 0;
623: availableAt = uint64(block.timestamp) + unstakingDelay;
628: queue.push(CumulativeDraft(uint176(oldDrafts + draftAmount), availableAt));
640: era++;
640: era++;
652: draftEra++;
652: draftEra++;
659: return rsr.balanceOf(address(this)) - stakeRSR - draftRSR;
659: return rsr.balanceOf(address(this)) - stakeRSR - draftRSR;
666: uint48 lastRefresh = assetRegistry.lastRefresh(); // {s}
666: uint48 lastRefresh = assetRegistry.lastRefresh(); // {s}
669: uint256 totalRSR = stakeRSR + draftRSR + rsrWithdrawal; // {qRSR}
669: uint256 totalRSR = stakeRSR + draftRSR + rsrWithdrawal; // {qRSR}
669: uint256 totalRSR = stakeRSR + draftRSR + rsrWithdrawal; // {qRSR}
669: uint256 totalRSR = stakeRSR + draftRSR + rsrWithdrawal; // {qRSR}
670: uint192 withdrawal = _safeWrap((rsrWithdrawal * FIX_ONE + totalRSR - 1) / totalRSR); // {1}
670: uint192 withdrawal = _safeWrap((rsrWithdrawal * FIX_ONE + totalRSR - 1) / totalRSR); // {1}
670: uint192 withdrawal = _safeWrap((rsrWithdrawal * FIX_ONE + totalRSR - 1) / totalRSR); // {1}
670: uint192 withdrawal = _safeWrap((rsrWithdrawal * FIX_ONE + totalRSR - 1) / totalRSR); // {1}
670: uint192 withdrawal = _safeWrap((rsrWithdrawal * FIX_ONE + totalRSR - 1) / totalRSR); // {1}
670: uint192 withdrawal = _safeWrap((rsrWithdrawal * FIX_ONE + totalRSR - 1) / totalRSR); // {1}
673: leaked = lastWithdrawRefresh != lastRefresh ? withdrawal : leaked + withdrawal;
692: uint256 newStakeRSR = stakeRSR + rsrAmount;
694: uint256 newTotalStakes = (stakeRate * newStakeRSR) / FIX_ONE;
694: uint256 newTotalStakes = (stakeRate * newStakeRSR) / FIX_ONE;
695: uint256 stakeAmount = newTotalStakes - totalStakes;
698: stakeRSR += rsrAmount;
768: _approve(owner, spender, _allowances[era][owner][spender] + addedValue);
777: _approve(owner, spender, currentAllowance - subtractedValue);
797: eraStakes[from] = fromBalance - amount;
799: eraStakes[to] += amount;
811: assert(totalStakes + amount < type(uint224).max);
813: stakes[era][account] += amount;
814: totalStakes += amount;
834: eraStakes[account] = accountBalance - amount;
836: totalStakes -= amount;
863: _approve(owner, spender, currentAllowance - amount);
File: contracts/p1/StRSRVotes.sol
4: import "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol";
6: import "../interfaces/IStRSRVotes.sol";
6: import "../interfaces/IStRSRVotes.sol";
7: import "./StRSR.sol";
34: Checkpoint[] private _eras; // {era}
34: Checkpoint[] private _eras; // {era}
38: mapping(uint256 => mapping(address => Checkpoint[])) private _checkpoints; // {qStRSR}
38: mapping(uint256 => mapping(address => Checkpoint[])) private _checkpoints; // {qStRSR}
40: mapping(uint256 => Checkpoint[]) private _totalSupplyCheckpoints; // {qStRSR}
40: mapping(uint256 => Checkpoint[]) private _totalSupplyCheckpoints; // {qStRSR}
73: return pos == 0 ? 0 : _checkpoints[era][account][pos - 1].val;
108: low = mid + 1;
111: return high == 0 ? 0 : ckpts[high - 1].val;
215: oldWeight = pos == 0 ? 0 : ckpts[pos - 1].val;
218: if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) {
219: ckpts[pos - 1].val = SafeCastUpgradeable.toUint224(newWeight);
231: return a + b;
235: return a - b;
File: contracts/p1/mixins/BasketLib.sol
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
5: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
5: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
5: import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
7: import "../../interfaces/IAssetRegistry.sol";
7: import "../../interfaces/IAssetRegistry.sol";
7: import "../../interfaces/IAssetRegistry.sol";
8: import "../../libraries/Fixed.sol";
8: import "../../libraries/Fixed.sol";
8: import "../../libraries/Fixed.sol";
14: uint256 max; // Maximum number of backup collateral erc20s to use in a basket
14: uint256 max; // Maximum number of backup collateral erc20s to use in a basket
15: IERC20[] erc20s; // Ordered list of backup collateral ERC20s
15: IERC20[] erc20s; // Ordered list of backup collateral ERC20s
48: IERC20[] erc20s; // enumerated keys for refAmts
48: IERC20[] erc20s; // enumerated keys for refAmts
49: mapping(IERC20 => uint192) refAmts; // {ref/BU}
49: mapping(IERC20 => uint192) refAmts; // {ref/BU}
49: mapping(IERC20 => uint192) refAmts; // {ref/BU}
70: for (uint256 i = 0; i < length; ++i) self.refAmts[self.erc20s[i]] = FIX_ZERO;
70: for (uint256 i = 0; i < length; ++i) self.refAmts[self.erc20s[i]] = FIX_ZERO;
78: for (uint256 i = 0; i < length; ++i) {
78: for (uint256 i = 0; i < length; ++i) {
108: - the basket configuration (config: BasketConfig)
109: - the function (isGood: erc20 -> bool), implemented here by goodCollateral()
109: - the function (isGood: erc20 -> bool), implemented here by goodCollateral()
110: - the function (targetPerRef: erc20 -> Fix) implemented by the Collateral plugin
110: - the function (targetPerRef: erc20 -> Fix) implemented by the Collateral plugin
117: Let targetWeight(b, e) = b.refAmt[e] * targetPerRef(e)
128: then unsoundPrimeWt(tgt) / len(Backups(tgt))
137: Else, return true and targetWeight(basket', e) == primeWt(e) + backupWt(e) for all e.
139: ==== Higher-level desideratum ====
175: for (uint256 i = 0; i < config.erc20s.length; ++i) {
175: for (uint256 i = 0; i < config.erc20s.length; ++i) {
193: for (uint256 i = 0; i < config.erc20s.length; ++i) {
193: for (uint256 i = 0; i < config.erc20s.length; ++i) {
196: for (targetIndex = 0; targetIndex < targetsLength; ++targetIndex) {
196: for (targetIndex = 0; targetIndex < targetsLength; ++targetIndex) {
238: for (uint256 i = 0; i < targetsLength; ++i) {
238: for (uint256 i = 0; i < targetsLength; ++i) {
239: if (totalWeights[i].lte(goodWeights[i])) continue; // Don't need any backup weight
239: if (totalWeights[i].lte(goodWeights[i])) continue; // Don't need any backup weight
244: uint256 size = 0; // backup basket size
244: uint256 size = 0; // backup basket size
248: for (uint256 j = 0; j < backup.erc20s.length && size < backup.max; ++j) {
248: for (uint256 j = 0; j < backup.erc20s.length && size < backup.max; ++j) {
249: if (goodCollateral(targetNames.at(i), backup.erc20s[j], assetRegistry)) size++;
249: if (goodCollateral(targetNames.at(i), backup.erc20s[j], assetRegistry)) size++;
259: for (uint256 j = 0; j < backup.erc20s.length && assigned < size; ++j) {
259: for (uint256 j = 0; j < backup.erc20s.length && assigned < size; ++j) {
271: assigned++;
271: assigned++;
File: contracts/p1/mixins/Component.sol
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
7: import "../../interfaces/IComponent.sol";
7: import "../../interfaces/IComponent.sol";
7: import "../../interfaces/IComponent.sol";
8: import "../../interfaces/IMain.sol";
8: import "../../interfaces/IMain.sol";
8: import "../../interfaces/IMain.sol";
9: import "../../mixins/Versioned.sol";
9: import "../../mixins/Versioned.sol";
9: import "../../mixins/Versioned.sol";
File: contracts/p1/mixins/RecollateralizationLib.sol
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "../../interfaces/IAsset.sol";
5: import "../../interfaces/IAsset.sol";
5: import "../../interfaces/IAsset.sol";
6: import "../../interfaces/IAssetRegistry.sol";
6: import "../../interfaces/IAssetRegistry.sol";
6: import "../../interfaces/IAssetRegistry.sol";
7: import "../../interfaces/IBackingManager.sol";
7: import "../../interfaces/IBackingManager.sol";
7: import "../../interfaces/IBackingManager.sol";
8: import "../../libraries/Fixed.sol";
8: import "../../libraries/Fixed.sol";
8: import "../../libraries/Fixed.sol";
9: import "./TradeLib.sol";
16: BasketRange basketsHeld; // {BU}
16: BasketRange basketsHeld; // {BU}
28: uint192 minTradeVolume; // {UoA}
28: uint192 minTradeVolume; // {UoA}
29: uint192 maxTradeSlippage; // {1}
29: uint192 maxTradeSlippage; // {1}
31: uint192[] quantities; // {tok/BU} basket quantities
31: uint192[] quantities; // {tok/BU} basket quantities
31: uint192[] quantities; // {tok/BU} basket quantities
81: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
81: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
156: (uint192 buPriceLow, uint192 buPriceHigh) = ctx.bh.price(); // {UoA/BU}
156: (uint192 buPriceLow, uint192 buPriceHigh) = ctx.bh.price(); // {UoA/BU}
156: (uint192 buPriceLow, uint192 buPriceHigh) = ctx.bh.price(); // {UoA/BU}
157: uint192 basketsNeeded = ctx.rToken.basketsNeeded(); // {BU}
157: uint192 basketsNeeded = ctx.rToken.basketsNeeded(); // {BU}
170: int256 deltaTop; // D18{BU} even though this is int256, it is D18
170: int256 deltaTop; // D18{BU} even though this is int256, it is D18
174: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
174: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
178: uint192 bal = reg.assets[i].bal(address(ctx.bm)); // {tok}
178: uint192 bal = reg.assets[i].bal(address(ctx.bm)); // {tok}
187: (uint192 lotLow, ) = reg.assets[i].lotPrice(); // {UoA/tok}
187: (uint192 lotLow, ) = reg.assets[i].lotPrice(); // {UoA/tok}
187: (uint192 lotLow, ) = reg.assets[i].lotPrice(); // {UoA/tok}
195: (uint192 low, uint192 high) = reg.assets[i].price(); // {UoA/tok}
195: (uint192 low, uint192 high) = reg.assets[i].price(); // {UoA/tok}
195: (uint192 low, uint192 high) = reg.assets[i].price(); // {UoA/tok}
210: deltaTop -= int256(uint256(low.mulDiv(anchor - bal, buPriceHigh, FLOOR)));
210: deltaTop -= int256(uint256(low.mulDiv(anchor - bal, buPriceHigh, FLOOR)));
216: deltaTop += int256(
217: uint256(ctx.bm.safeMulDivCeil(high, bal - anchor, buPriceLow))
231: uint192 val = low.mul(bal - anchor, FLOOR);
240: val = (val < ctx.minTradeVolume) ? 0 : val - ctx.minTradeVolume;
245: range.bottom += val.mulDiv(FIX_ONE.minus(ctx.maxTradeSlippage), buPriceHigh, FLOOR);
253: range.top = ctx.basketsHeld.top - _safeWrap(uint256(-deltaTop));
253: range.top = ctx.basketsHeld.top - _safeWrap(uint256(-deltaTop));
257: if (uint256(deltaTop) + ctx.basketsHeld.top > FIX_MAX) range.top = FIX_MAX;
258: else range.top = ctx.basketsHeld.top + _safeWrap(uint256(deltaTop));
262: range.bottom += ctx.basketsHeld.bottom;
277: CollateralStatus surplusStatus; // starts SOUND
277: CollateralStatus surplusStatus; // starts SOUND
278: uint192 surplus; // {UoA}
278: uint192 surplus; // {UoA}
279: uint192 deficit; // {UoA}
279: uint192 deficit; // {UoA}
317: maxes.surplusStatus = CollateralStatus.IFFY; // least-desirable sell status
317: maxes.surplusStatus = CollateralStatus.IFFY; // least-desirable sell status
317: maxes.surplusStatus = CollateralStatus.IFFY; // least-desirable sell status
321: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
321: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
324: uint192 bal = reg.assets[i].bal(address(ctx.bm)); // {tok}
324: uint192 bal = reg.assets[i].bal(address(ctx.bm)); // {tok}
328: uint192 needed = range.top.mul(ctx.quantities[i], CEIL); // {tok}
328: uint192 needed = range.top.mul(ctx.quantities[i], CEIL); // {tok}
331: uint192 low; // {UoA/sellTok}
331: uint192 low; // {UoA/sellTok}
331: uint192 low; // {UoA/sellTok}
335: uint192 high; // {UoA/sellTok}
335: uint192 high; // {UoA/sellTok}
335: uint192 high; // {UoA/sellTok}
336: (low, high) = reg.assets[i].price(); // {UoA/sellTok}
336: (low, high) = reg.assets[i].price(); // {UoA/sellTok}
336: (low, high) = reg.assets[i].price(); // {UoA/sellTok}
342: (uint192 lotLow, ) = reg.assets[i].lotPrice(); // {UoA/sellTok}
342: (uint192 lotLow, ) = reg.assets[i].lotPrice(); // {UoA/sellTok}
342: (uint192 lotLow, ) = reg.assets[i].lotPrice(); // {UoA/sellTok}
348: CollateralStatus status; // starts SOUND
348: CollateralStatus status; // starts SOUND
373: needed = range.bottom.mul(ctx.quantities[i], CEIL); // {buyTok};
373: needed = range.bottom.mul(ctx.quantities[i], CEIL); // {buyTok};
376: uint192 amtShort = needed.minus(bal); // {buyTok}
376: uint192 amtShort = needed.minus(bal); // {buyTok}
377: (, uint192 high) = reg.assets[i].price(); // {UoA/buyTok}
377: (, uint192 high) = reg.assets[i].price(); // {UoA/buyTok}
377: (, uint192 high) = reg.assets[i].price(); // {UoA/buyTok}
401: (uint192 low, uint192 high) = rsrAsset.price(); // {UoA/tok}
401: (uint192 low, uint192 high) = rsrAsset.price(); // {UoA/tok}
401: (uint192 low, uint192 high) = rsrAsset.price(); // {UoA/tok}
402: (uint192 lotLow, ) = rsrAsset.lotPrice(); // {UoA/tok}
402: (uint192 lotLow, ) = rsrAsset.lotPrice(); // {UoA/tok}
402: (uint192 lotLow, ) = rsrAsset.lotPrice(); // {UoA/tok}
File: contracts/p1/mixins/RewardableLib.sol
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6: import "@openzeppelin/contracts/utils/Address.sol";
6: import "@openzeppelin/contracts/utils/Address.sol";
6: import "@openzeppelin/contracts/utils/Address.sol";
7: import "../../interfaces/IAssetRegistry.sol";
7: import "../../interfaces/IAssetRegistry.sol";
7: import "../../interfaces/IAssetRegistry.sol";
8: import "../../interfaces/IBackingManager.sol";
8: import "../../interfaces/IBackingManager.sol";
8: import "../../interfaces/IBackingManager.sol";
27: for (uint256 i = 0; i < registry.erc20s.length; ++i) {
27: for (uint256 i = 0; i < registry.erc20s.length; ++i) {
File: contracts/p1/mixins/TradeLib.sol
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import "../../interfaces/IAsset.sol";
5: import "../../interfaces/IAsset.sol";
5: import "../../interfaces/IAsset.sol";
6: import "../../interfaces/IAssetRegistry.sol";
6: import "../../interfaces/IAssetRegistry.sol";
6: import "../../interfaces/IAssetRegistry.sol";
7: import "../../interfaces/ITrading.sol";
7: import "../../interfaces/ITrading.sol";
7: import "../../interfaces/ITrading.sol";
8: import "../../libraries/Fixed.sol";
8: import "../../libraries/Fixed.sol";
8: import "../../libraries/Fixed.sol";
9: import "./RecollateralizationLib.sol";
14: uint192 sellAmount; // {sellTok}
14: uint192 sellAmount; // {sellTok}
15: uint192 buyAmount; // {buyTok}
15: uint192 buyAmount; // {buyTok}
16: uint192 sellPrice; // {UoA/sellTok} can be 0
16: uint192 sellPrice; // {UoA/sellTok} can be 0
16: uint192 sellPrice; // {UoA/sellTok} can be 0
17: uint192 buyPrice; // {UoA/buyTok}
17: uint192 buyPrice; // {UoA/buyTok}
17: uint192 buyPrice; // {UoA/buyTok}
59: uint192 maxSell = maxTradeSize(trade.sell, trade.buy, lotHigh); // {sellTok}
59: uint192 maxSell = maxTradeSize(trade.sell, trade.buy, lotHigh); // {sellTok}
60: uint192 s = trade.sellAmount > maxSell ? maxSell : trade.sellAmount; // {sellTok}
60: uint192 s = trade.sellAmount > maxSell ? maxSell : trade.sellAmount; // {sellTok}
67: trade.sellPrice, // {UoA/sellTok}
67: trade.sellPrice, // {UoA/sellTok}
67: trade.sellPrice, // {UoA/sellTok}
68: trade.buyPrice // {UoA/buyTok}
68: trade.buyPrice // {UoA/buyTok}
68: trade.buyPrice // {UoA/buyTok}
130: trade.sellAmount = fixMin(slippedSellAmount, trade.sellAmount); // {sellTok}
130: trade.sellAmount = fixMin(slippedSellAmount, trade.sellAmount); // {sellTok}
File: contracts/p1/mixins/Trading.sol
4: import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
4: import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
5: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
6: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6: import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
7: import "@openzeppelin/contracts/utils/Multicall.sol";
7: import "@openzeppelin/contracts/utils/Multicall.sol";
7: import "@openzeppelin/contracts/utils/Multicall.sol";
8: import "../../interfaces/ITrade.sol";
8: import "../../interfaces/ITrade.sol";
8: import "../../interfaces/ITrade.sol";
9: import "../../interfaces/ITrading.sol";
9: import "../../interfaces/ITrading.sol";
9: import "../../interfaces/ITrading.sol";
10: import "../../libraries/Fixed.sol";
10: import "../../libraries/Fixed.sol";
10: import "../../libraries/Fixed.sol";
11: import "./Component.sol";
12: import "./RewardableLib.sol";
23: uint192 public constant MAX_TRADE_VOLUME = 1e29; // {UoA}
23: uint192 public constant MAX_TRADE_VOLUME = 1e29; // {UoA}
24: uint192 public constant MAX_TRADE_SLIPPAGE = 1e18; // {%}
24: uint192 public constant MAX_TRADE_SLIPPAGE = 1e18; // {%}
34: uint192 public maxTradeSlippage; // {%}
34: uint192 public maxTradeSlippage; // {%}
36: uint192 public minTradeVolume; // {UoA}
36: uint192 public minTradeVolume; // {UoA}
93: tradesOpen--;
93: tradesOpen--;
123: tradesOpen++;
123: tradesOpen++;
File: contracts/plugins/governance/Governance.sol
4: import "@openzeppelin/contracts/governance/Governor.sol";
4: import "@openzeppelin/contracts/governance/Governor.sol";
4: import "@openzeppelin/contracts/governance/Governor.sol";
5: import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
5: import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
5: import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
5: import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
6: import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
6: import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
6: import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
6: import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
7: import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
7: import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
7: import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
7: import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
8: import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
8: import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
8: import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
8: import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
9: import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
9: import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
9: import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
9: import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
10: import "../../interfaces/IStRSRVotes.sol";
10: import "../../interfaces/IStRSRVotes.sol";
10: import "../../interfaces/IStRSRVotes.sol";
31: uint256 public constant ONE_HUNDRED_PERCENT = 1e8; // {micro %}
31: uint256 public constant ONE_HUNDRED_PERCENT = 1e8; // {micro %}
37: uint256 votingDelay_, // in blocks
37: uint256 votingDelay_, // in blocks
38: uint256 votingPeriod_, // in blocks
38: uint256 votingPeriod_, // in blocks
39: uint256 proposalThresholdAsMicroPercent_, // e.g. 1e4 for 0.01%
39: uint256 proposalThresholdAsMicroPercent_, // e.g. 1e4 for 0.01%
40: uint256 quorumPercent // e.g 4 for 4%
40: uint256 quorumPercent // e.g 4 for 4%
66: uint256 asMicroPercent = super.proposalThreshold(); // {micro %}
66: uint256 asMicroPercent = super.proposalThreshold(); // {micro %}
67: uint256 pastSupply = token.getPastTotalSupply(block.number - 1); // {qStRSR}
67: uint256 pastSupply = token.getPastTotalSupply(block.number - 1); // {qStRSR}
67: uint256 pastSupply = token.getPastTotalSupply(block.number - 1); // {qStRSR}
71: return (asMicroPercent * pastSupply + (ONE_HUNDRED_PERCENT - 1)) / ONE_HUNDRED_PERCENT;
71: return (asMicroPercent * pastSupply + (ONE_HUNDRED_PERCENT - 1)) / ONE_HUNDRED_PERCENT;
71: return (asMicroPercent * pastSupply + (ONE_HUNDRED_PERCENT - 1)) / ONE_HUNDRED_PERCENT;
71: return (asMicroPercent * pastSupply + (ONE_HUNDRED_PERCENT - 1)) / ONE_HUNDRED_PERCENT;
156: bytes memory /*params*/
156: bytes memory /*params*/
156: bytes memory /*params*/
156: bytes memory /*params*/
158: return token.getPastVotes(account, blockNumber); // {qStRSR}
158: return token.getPastVotes(account, blockNumber); // {qStRSR}
File: contracts/plugins/trading/DutchTrade.sol
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
5: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
5: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
6: import "../../libraries/Fixed.sol";
6: import "../../libraries/Fixed.sol";
6: import "../../libraries/Fixed.sol";
7: import "../../interfaces/IAsset.sol";
7: import "../../interfaces/IAsset.sol";
7: import "../../interfaces/IAsset.sol";
8: import "../../interfaces/ITrade.sol";
8: import "../../interfaces/ITrade.sol";
8: import "../../interfaces/ITrade.sol";
10: uint192 constant FORTY_PERCENT = 4e17; // {1} 0.4
10: uint192 constant FORTY_PERCENT = 4e17; // {1} 0.4
11: uint192 constant SIXTY_PERCENT = 6e17; // {1} 0.6
11: uint192 constant SIXTY_PERCENT = 6e17; // {1} 0.6
19: uint192 constant MAX_EXP = 6907752 * FIX_ONE; // {1} (1000000/999999)^6907752 = ~1000x
19: uint192 constant MAX_EXP = 6907752 * FIX_ONE; // {1} (1000000/999999)^6907752 = ~1000x
19: uint192 constant MAX_EXP = 6907752 * FIX_ONE; // {1} (1000000/999999)^6907752 = ~1000x
19: uint192 constant MAX_EXP = 6907752 * FIX_ONE; // {1} (1000000/999999)^6907752 = ~1000x
20: uint192 constant BASE = 999999e12; // {1} (999999/1000000)
20: uint192 constant BASE = 999999e12; // {1} (999999/1000000)
20: uint192 constant BASE = 999999e12; // {1} (999999/1000000)
47: TradeStatus public status; // reentrancy protection
47: TradeStatus public status; // reentrancy protection
49: ITrading public origin; // the address that initialized the contract
49: ITrading public origin; // the address that initialized the contract
54: uint192 public sellAmount; // {sellTok}
54: uint192 public sellAmount; // {sellTok}
57: uint48 public startTime; // {s} when the dutch auction begins (12s after init())
57: uint48 public startTime; // {s} when the dutch auction begins (12s after init())
58: uint48 public endTime; // {s} when the dutch auction ends if no bids are received
58: uint48 public endTime; // {s} when the dutch auction ends if no bids are received
61: uint192 public middlePrice; // {buyTok/sellTok} The price at which the function is piecewise
61: uint192 public middlePrice; // {buyTok/sellTok} The price at which the function is piecewise
61: uint192 public middlePrice; // {buyTok/sellTok} The price at which the function is piecewise
62: uint192 public lowPrice; // {buyTok/sellTok} The price the auction ends at
62: uint192 public lowPrice; // {buyTok/sellTok} The price the auction ends at
62: uint192 public lowPrice; // {buyTok/sellTok} The price the auction ends at
110: auctionLength >= 2 * ONE_BLOCK
111: ); // misuse by caller
111: ); // misuse by caller
114: (uint192 sellLow, uint192 sellHigh) = sell_.price(); // {UoA/sellTok}
114: (uint192 sellLow, uint192 sellHigh) = sell_.price(); // {UoA/sellTok}
114: (uint192 sellLow, uint192 sellHigh) = sell_.price(); // {UoA/sellTok}
115: (uint192 buyLow, uint192 buyHigh) = buy_.price(); // {UoA/buyTok}
115: (uint192 buyLow, uint192 buyHigh) = buy_.price(); // {UoA/buyTok}
115: (uint192 buyLow, uint192 buyHigh) = buy_.price(); // {UoA/buyTok}
124: sellAmount = shiftl_toFix(sellAmount_, -int8(sell.decimals())); // {sellTok}
124: sellAmount = shiftl_toFix(sellAmount_, -int8(sell.decimals())); // {sellTok}
124: sellAmount = shiftl_toFix(sellAmount_, -int8(sell.decimals())); // {sellTok}
125: startTime = uint48(block.timestamp) + ONE_BLOCK; // start in the next block
125: startTime = uint48(block.timestamp) + ONE_BLOCK; // start in the next block
125: startTime = uint48(block.timestamp) + ONE_BLOCK; // start in the next block
126: endTime = startTime + auctionLength;
130: sellAmount.mul(sellHigh, FLOOR), // auctionVolume
130: sellAmount.mul(sellHigh, FLOOR), // auctionVolume
131: origin.minTradeVolume(), // minTradeVolume
131: origin.minTradeVolume(), // minTradeVolume
132: fixMin(sell_.maxTradeVolume(), buy_.maxTradeVolume()) // maxTradeVolume
132: fixMin(sell_.maxTradeVolume(), buy_.maxTradeVolume()) // maxTradeVolume
136: lowPrice = sellLow.mulDiv(FIX_ONE - slippage, buyHigh, FLOOR);
137: middlePrice = sellHigh.div(buyLow, CEIL); // no additional slippage
137: middlePrice = sellHigh.div(buyLow, CEIL); // no additional slippage
150: amountIn = bidAmount(uint48(block.timestamp)); // enforces auction ongoing
150: amountIn = bidAmount(uint48(block.timestamp)); // enforces auction ongoing
184: soldAmt = sellAmount > sellBal ? sellAmount - sellBal : 0;
218: slippage = origin.maxTradeSlippage(); // {1}
218: slippage = origin.maxTradeSlippage(); // {1}
220: if (auctionVolume > maxTradeVolume) return 0; // 0% slippage beyond maxTradeVolume
220: if (auctionVolume > maxTradeVolume) return 0; // 0% slippage beyond maxTradeVolume
225: FIX_ONE - divuu(auctionVolume - minTradeVolume, maxTradeVolume - minTradeVolume)
225: FIX_ONE - divuu(auctionVolume - minTradeVolume, maxTradeVolume - minTradeVolume)
225: FIX_ONE - divuu(auctionVolume - minTradeVolume, maxTradeVolume - minTradeVolume)
237: uint192 progression = divuu(timestamp - startTime, endTime - startTime); // {1}
237: uint192 progression = divuu(timestamp - startTime, endTime - startTime); // {1}
237: uint192 progression = divuu(timestamp - startTime, endTime - startTime); // {1}
237: uint192 progression = divuu(timestamp - startTime, endTime - startTime); // {1}
241: uint192 exp = MAX_EXP.mulDiv(FORTY_PERCENT - progression, FORTY_PERCENT, ROUND);
252: middlePrice -
253: (middlePrice - lowPrice).mulDiv(progression - FORTY_PERCENT, SIXTY_PERCENT);
253: (middlePrice - lowPrice).mulDiv(progression - FORTY_PERCENT, SIXTY_PERCENT);
File: contracts/plugins/trading/GnosisTrade.sol
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
4: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
5: import "@openzeppelin/contracts/utils/math/Math.sol";
5: import "@openzeppelin/contracts/utils/math/Math.sol";
5: import "@openzeppelin/contracts/utils/math/Math.sol";
5: import "@openzeppelin/contracts/utils/math/Math.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
6: import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
7: import "../../libraries/Fixed.sol";
7: import "../../libraries/Fixed.sol";
7: import "../../libraries/Fixed.sol";
8: import "../../interfaces/IBroker.sol";
8: import "../../interfaces/IBroker.sol";
8: import "../../interfaces/IBroker.sol";
9: import "../../interfaces/IGnosis.sol";
9: import "../../interfaces/IGnosis.sol";
9: import "../../interfaces/IGnosis.sol";
10: import "../../interfaces/ITrade.sol";
10: import "../../interfaces/ITrade.sol";
10: import "../../interfaces/ITrade.sol";
28: uint192 public constant DEFAULT_MIN_BID = FIX_ONE / 100; // {tok}
28: uint192 public constant DEFAULT_MIN_BID = FIX_ONE / 100; // {tok}
28: uint192 public constant DEFAULT_MIN_BID = FIX_ONE / 100; // {tok}
35: IGnosis public gnosis; // Gnosis Auction contract
35: IGnosis public gnosis; // Gnosis Auction contract
36: uint256 public auctionId; // The Gnosis Auction ID returned by gnosis.initiateAuction()
36: uint256 public auctionId; // The Gnosis Auction ID returned by gnosis.initiateAuction()
37: IBroker public broker; // The Broker that cloned this contract into existence
37: IBroker public broker; // The Broker that cloned this contract into existence
43: IERC20Metadata public sell; // address of token this trade is selling
43: IERC20Metadata public sell; // address of token this trade is selling
44: IERC20Metadata public buy; // address of token this trade is buying
44: IERC20Metadata public buy; // address of token this trade is buying
45: uint256 public initBal; // {qTok}, this trade's balance of `sell` when init() was called
45: uint256 public initBal; // {qTok}, this trade's balance of `sell` when init() was called
46: uint48 public endTime; // timestamp after which this trade's auction can be settled
46: uint48 public endTime; // timestamp after which this trade's auction can be settled
47: uint192 public worstCasePrice; // {buyTok/sellTok}, the worst price we expect to get at Auction
47: uint192 public worstCasePrice; // {buyTok/sellTok}, the worst price we expect to get at Auction
47: uint192 public worstCasePrice; // {buyTok/sellTok}, the worst price we expect to get at Auction
97: endTime = uint48(block.timestamp) + batchAuctionLength;
100: worstCasePrice = shiftl_toFix(req.minBuyAmount, -int8(buy.decimals())).div(
101: shiftl_toFix(req.sellAmount, -int8(sell.decimals()))
108: req.sellAmount * FEE_DENOMINATOR,
109: FEE_DENOMINATOR + gnosis.feeNumerator(),
115: uint96 minBuyAmount = uint96(Math.max(1, req.minBuyAmount)); // Safe downcast; require'd
115: uint96 minBuyAmount = uint96(Math.max(1, req.minBuyAmount)); // Safe downcast; require'd
118: minBuyAmount / MAX_ORDERS,
190: soldAmt = initBal - sellBal;
194: uint256 adjustedBuyAmt = boughtAmt + 1;
197: uint192 clearingPrice = shiftl_toFix(adjustedBuyAmt, -int8(buy.decimals())).div(
198: shiftl_toFix(adjustedSoldAmt, -int8(sell.decimals()))
Source Instead of using error strings, to reduce deployment and runtime cost, you should use Custom Errors. This would save both deployment and runtime cost.
Instances (163):
File: contracts/libraries/Throttle.sol
53: require(uint256(amount) <= available, "supply change throttled");
File: contracts/mixins/Auth.sol
92: require(account != address(0), "cannot grant role to address 0");
199: require(shortFreeze_ > 0 && shortFreeze_ <= MAX_SHORT_FREEZE, "short freeze out of range");
206: require(longFreeze_ > 0 && longFreeze_ <= MAX_LONG_FREEZE, "long freeze out of range");
215: require(newUnfreezeAt > unfreezeAt, "frozen");
File: contracts/mixins/ComponentRegistry.sol
37: require(address(val) != address(0), "invalid RToken address");
45: require(address(val) != address(0), "invalid StRSR address");
53: require(address(val) != address(0), "invalid AssetRegistry address");
61: require(address(val) != address(0), "invalid BasketHandler address");
69: require(address(val) != address(0), "invalid BackingManager address");
77: require(address(val) != address(0), "invalid Distributor address");
85: require(address(val) != address(0), "invalid RSRTrader address");
93: require(address(val) != address(0), "invalid RTokenTrader address");
101: require(address(val) != address(0), "invalid Furnace address");
109: require(address(val) != address(0), "invalid Broker address");
File: contracts/p1/AssetRegistry.sol
87: require(_erc20s.contains(address(asset.erc20())), "no ERC20 collision");
103: require(_erc20s.contains(address(asset.erc20())), "no asset to unregister");
104: require(assets[asset.erc20()] == asset, "asset not found");
121: require(_erc20s.contains(address(erc20)), "erc20 unregistered");
129: require(_erc20s.contains(address(erc20)), "erc20 unregistered");
130: require(assets[erc20].isCollateral(), "erc20 is not collateral");
210: require(gas > GAS_TO_RESERVE, "not enough gas to unregister safely");
File: contracts/p1/BackingManager.sol
67: require(assetRegistry.isRegistered(erc20), "erc20 unregistered");
116: require(tradesOpen == 0, "trade open");
117: require(basketHandler.isReady(), "basket not ready");
118: require(block.timestamp >= basketHandler.timestamp() + tradingDelay, "trading delayed");
121: require(basketsHeld.bottom < rToken.basketsNeeded(), "already collateralized");
173: require(ArrayLib.allUnique(erc20s), "duplicate tokens");
180: require(tradesOpen == 0, "trade open");
181: require(basketHandler.isReady(), "basket not ready");
182: require(block.timestamp >= basketHandler.timestamp() + tradingDelay, "trading delayed");
183: require(basketsHeld.bottom >= rToken.basketsNeeded(), "undercollateralized");
269: require(val <= MAX_TRADING_DELAY, "invalid tradingDelay");
276: require(val <= MAX_BACKING_BUFFER, "invalid backingBuffer");
File: contracts/p1/BasketHandler.sol
115: require(_msgSender() == address(assetRegistry), "asset registry only");
177: require(erc20s.length > 0, "cannot empty basket");
178: require(erc20s.length == targetAmts.length, "must be same length");
197: require(assetRegistry.toAsset(erc20s[i]).isCollateral(), "erc20 is not collateral");
198: require(0 < targetAmts[i], "invalid target amount; must be nonzero");
199: require(targetAmts[i] <= MAX_TARGET_AMT, "invalid target amount; too large");
232: require(assetRegistry.toAsset(erc20s[i]).isCollateral(), "erc20 is not collateral");
389: require(basketNonces.length == portions.length, "portions does not mirror basketNonces");
398: require(basketNonces[i] <= nonce, "invalid basketNonce");
493: require(val >= MIN_WARMUP_PERIOD && val <= MAX_WARMUP_PERIOD, "invalid warmupPeriod");
557: require(contains && amt >= newTargetAmts[i], "new basket adds target weights");
561: require(_targetAmts.length() == 0, "new basket missing target weights");
569: require(erc20s[i] != rsr, "RSR is not valid collateral");
570: require(erc20s[i] != IERC20(address(rToken)), "RToken is not valid collateral");
571: require(erc20s[i] != IERC20(address(stRSR)), "stRSR is not valid collateral");
572: require(erc20s[i] != zero, "address zero is not valid collateral");
575: require(ArrayLib.allUnique(erc20s), "contains duplicates");
File: contracts/p1/Broker.sol
98: require(!disabled, "broker disabled");
120: require(trades[_msgSender()], "unrecognized trade contract");
129: require(address(newGnosis) != address(0), "invalid Gnosis address");
188: require(batchAuctionLength > 0, "batch auctions not enabled");
212: require(dutchAuctionLength > 0, "dutch auctions not enabled");
File: contracts/p1/Deployer.sol
110: require(owner != address(0) && owner != address(this), "invalid owner");
File: contracts/p1/Distributor.sol
88: require(erc20 == rsr || erc20 == rToken, "RSR or RToken");
94: require(totalShares > 0, "nothing to distribute");
158: require(dest != address(0), "dest cannot be zero");
163: if (dest == FURNACE) require(share.rsrDist == 0, "Furnace must get 0% of RSR");
164: if (dest == ST_RSR) require(share.rTokenDist == 0, "StRSR must get 0% of RToken");
165: require(share.rsrDist <= MAX_DISTRIBUTION, "RSR distribution too high");
166: require(share.rTokenDist <= MAX_DISTRIBUTION, "RToken distribution too high");
172: require(destinations.length() <= MAX_DESTINATIONS_ALLOWED, "Too many destinations");
182: require(rTokenDist > 0 || rsrDist > 0, "no distribution defined");
File: contracts/p1/Furnace.sol
87: require(ratio_ <= MAX_RATIO, "invalid ratio");
File: contracts/p1/Main.sol
32: require(address(rsr_) != address(0), "invalid RSR address");
48: require(!frozen(), "frozen");
File: contracts/p1/RToken.sol
69: require(bytes(name_).length > 0, "name empty");
70: require(bytes(symbol_).length > 0, "symbol empty");
71: require(bytes(mandate_).length > 0, "mandate empty");
102: require(amount > 0, "Cannot issue zero");
113: require(basketHandler.isReady(), "basket not ready");
188: require(amount > 0, "Cannot redeem zero");
189: require(amount <= balanceOf(_msgSender()), "insufficient balance");
190: require(basketHandler.fullyCollateralized(), "partial redemption; use redeemCustom");
261: require(amount > 0, "Cannot redeem zero");
262: require(amount <= balanceOf(_msgSender()), "insufficient balance");
267: require(portionsSum == FIX_ONE, "portions do not add up to FIX_ONE");
327: if (allZero) revert("empty redemption");
336: require(bal - pastBals[i] >= minAmounts[i], "redemption below minimum");
351: require(_msgSender() == address(backingManager), "not backing manager");
365: require(_msgSender() == address(furnace), "furnace only");
381: require(_msgSender() == address(backingManager), "not backing manager");
390: require(_msgSender() == address(backingManager), "not backing manager");
396: require(supply > 0, "0 supply");
405: require(low >= MIN_EXCHANGE_RATE && high <= MAX_EXCHANGE_RATE, "BU rate out of range");
411: require(assetRegistry.isRegistered(erc20), "erc20 unregistered");
445: require(params.amtRate >= MIN_THROTTLE_RATE_AMT, "issuance amtRate too small");
446: require(params.amtRate <= MAX_THROTTLE_RATE_AMT, "issuance amtRate too big");
447: require(params.pctRate <= MAX_THROTTLE_PCT_AMT, "issuance pctRate too big");
454: require(params.amtRate >= MIN_THROTTLE_RATE_AMT, "redemption amtRate too small");
455: require(params.amtRate <= MAX_THROTTLE_RATE_AMT, "redemption amtRate too big");
456: require(params.pctRate <= MAX_THROTTLE_PCT_AMT, "redemption pctRate too big");
524: require(to != address(this), "RToken transfer to self");
File: contracts/p1/RevenueTrader.sol
32: require(address(tokenToBuy_) != address(0), "invalid token address");
111: require(address(trades[erc20]) == address(0), "trade open");
112: require(erc20.balanceOf(address(this)) > 0, "0 balance");
117: require(buyPrice > 0 && buyPrice < FIX_MAX, "buy asset price unknown");
135: require(req.sellAmount > 1, "sell amount too low");
File: contracts/p1/StRSR.sol
177: require(bytes(name_).length > 0, "name empty");
178: require(bytes(symbol_).length > 0, "symbol empty");
223: require(rsrAmount > 0, "Cannot stake zero");
257: require(stakeAmount > 0, "Cannot withdraw zero");
258: require(stakes[era][account] >= stakeAmount, "Not enough balance");
306: require(endId <= queue.length, "index out-of-bounds");
307: require(queue[endId - 1].availableAt <= block.timestamp, "withdrawal unavailable");
335: require(basketHandler.fullyCollateralized(), "RToken uncollateralized");
336: require(basketHandler.isReady(), "basket not ready");
353: require(endId <= queue.length, "index out-of-bounds");
419: require(_msgSender() == address(backingManager), "not backing manager");
420: require(rsrAmount > 0, "Amount cannot be zero");
423: require(rsrAmount <= rsrBalance, "Cannot seize more RSR than we hold");
775: require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
790: require(from != address(0), "ERC20: transfer from the zero address");
791: require(to != address(0), "ERC20: transfer to the zero address");
795: require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
810: require(account != address(0), "ERC20: mint to the zero address");
826: require(account != address(0), "ERC20: burn from the zero address");
832: require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
847: require(owner != address(0), "ERC20: approve from the zero address");
848: require(spender != address(0), "ERC20: approve to the zero address");
861: require(currentAllowance >= amount, "ERC20: insufficient allowance");
875: require(to != address(this), "StRSR transfer to self");
890: require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
931: require(val > MIN_UNSTAKING_DELAY && val <= MAX_UNSTAKING_DELAY, "invalid unstakingDelay");
940: require(val <= MAX_REWARD_RATIO, "invalid rewardRatio");
948: require(val <= MAX_WITHDRAWAL_LEAK, "invalid withdrawalLeak");
File: contracts/p1/StRSRVotes.sol
77: require(blockNumber < block.number, "ERC20Votes: block not yet mined");
83: require(blockNumber < block.number, "ERC20Votes: block not yet mined");
89: require(blockNumber < block.number, "ERC20Votes: block not yet mined");
126: require(block.timestamp <= expiry, "ERC20Votes: signature expired");
133: require(nonce == _useDelegationNonce(signer), "ERC20Votes: invalid nonce");
File: contracts/p1/mixins/Component.sol
34: require(address(main_) != address(0), "main is zero address");
42: require(!main.tradingPausedOrFrozen(), "frozen or trading paused");
47: require(!main.issuancePausedOrFrozen(), "frozen or issuance paused");
52: require(!main.frozen(), "frozen");
57: require(main.hasRole(OWNER, _msgSender()), "governance only");
File: contracts/p1/mixins/Trading.sol
89: require(address(trade) != address(0), "no trade open");
90: require(trade.canSettle(), "cannot settle yet");
132: require(val < MAX_TRADE_SLIPPAGE, "invalid maxTradeSlippage");
139: require(val <= MAX_TRADE_VOLUME, "invalid minTradeVolume");
File: contracts/plugins/governance/Governance.sol
110: require(startedInSameEra(proposalId), "new era");
120: require(!startedInSameEra(proposalId), "same era");
131: require(startedInSameEra(proposalId), "new era");
File: contracts/plugins/trading/DutchTrade.sol
70: require(status == begin, "Invalid trade state");
83: require(timestamp >= startTime, "auction not started");
84: require(timestamp <= endTime, "auction over");
116: require(sellLow > 0 && sellHigh < FIX_MAX, "bad sell pricing");
117: require(buyLow > 0 && buyHigh < FIX_MAX, "bad buy pricing");
123: require(sellAmount_ <= sell.balanceOf(address(this)), "unfunded trade");
147: require(bidder == address(0), "bid already received");
174: require(msg.sender == address(origin), "only origin can settle");
180: require(block.timestamp >= endTime, "auction not over");
196: require(status == TradeStatus.CLOSED, "only after trade is closed");
File: contracts/plugins/trading/GnosisTrade.sol
54: require(status == begin, "Invalid trade state");
82: require(req.sellAmount <= type(uint96).max, "sellAmount too large");
83: require(req.minBuyAmount <= type(uint96).max, "minBuyAmount too large");
89: require(initBal <= type(uint96).max, "initBal too large");
90: require(initBal >= req.sellAmount, "unfunded trade");
168: require(msg.sender == origin, "only origin can settle");
211: require(status == TradeStatus.CLOSED, "only after trade is closed");
Instances (52):
File: contracts/libraries/Array.sol
12: for (uint256 j = 0; j < i; ++j) {
File: contracts/libraries/Fixed.sol
50: uint192 constant FIX_ZERO = 0; // The uint192 representation of zero.
53: uint192 constant FIX_MIN = 0; // The smallest uint192.
File: contracts/libraries/String.sol
14: for (uint256 i = 0; i < bStr.length; i++) {
File: contracts/p1/AssetRegistry.sol
46: for (uint256 i = 0; i < length; ++i) {
59: for (uint256 i = 0; i < length; ++i) {
145: for (uint256 i = 0; i < length; ++i) {
157: for (uint256 i = 0; i < length; ++i) {
File: contracts/p1/BackingManager.sol
226: for (uint256 i = 0; i < length; ++i) {
File: contracts/p1/BasketHandler.sol
119: for (uint256 i = 0; i < len; ++i) refAmts[i] = basket.refAmts[basket.erc20s[i]];
185: for (uint256 i = 0; i < config.erc20s.length; ++i) {
194: for (uint256 i = 0; i < erc20s.length; ++i) {
229: for (uint256 i = 0; i < erc20s.length; ++i) {
254: for (uint256 i = 0; i < size; ++i) {
331: for (uint256 i = 0; i < len; ++i) {
363: for (uint256 i = 0; i < length; ++i) {
397: for (uint48 i = 0; i < basketNonces.length; ++i) {
402: for (uint256 j = 0; j < b.erc20s.length; ++j) {
408: for (uint256 k = 0; k < len; ++k) {
434: for (uint256 i = 0; i < len; ++i) {
469: for (uint256 i = 0; i < length; ++i) {
523: for (uint256 i = 0; i < len; ++i) {
542: for (uint256 i = 0; i < len; ++i) {
554: for (uint256 i = 0; i < len; ++i) {
568: for (uint256 i = 0; i < erc20s.length; i++) {
594: for (uint256 i = 0; i < b.erc20s.length; ++i) {
633: for (uint256 i = 0; i < erc20s.length; ++i) {
651: for (uint256 i = 0; i < erc20s.length; ++i) {
File: contracts/p1/Distributor.sol
104: for (uint256 i = 0; i < destinations.length(); ++i) {
129: for (uint256 i = 0; i < numTransfers; i++) {
139: for (uint256 i = 0; i < length; ++i) {
File: contracts/p1/RToken.sol
144: for (uint256 i = 0; i < erc20s.length; ++i) {
207: for (uint256 i = 0; i < erc20s.length; ++i) {
264: for (uint256 i = 0; i < portions.length; ++i) {
292: for (uint256 i = 0; i < erc20sOut.length; ++i) {
306: for (uint256 i = 0; i < expectedERC20sOut.length; ++i) {
316: for (uint256 i = 0; i < erc20sOut.length; ++i) {
333: for (uint256 i = 0; i < expectedERC20sOut.length; ++i) {
File: contracts/p1/StRSRVotes.sol
102: uint256 low = 0;
File: contracts/p1/mixins/BasketLib.sol
70: for (uint256 i = 0; i < length; ++i) self.refAmts[self.erc20s[i]] = FIX_ZERO;
78: for (uint256 i = 0; i < length; ++i) {
175: for (uint256 i = 0; i < config.erc20s.length; ++i) {
193: for (uint256 i = 0; i < config.erc20s.length; ++i) {
238: for (uint256 i = 0; i < targetsLength; ++i) {
244: uint256 size = 0; // backup basket size
248: for (uint256 j = 0; j < backup.erc20s.length && size < backup.max; ++j) {
256: uint256 assigned = 0;
259: for (uint256 j = 0; j < backup.erc20s.length && assigned < size; ++j) {
File: contracts/p1/mixins/RecollateralizationLib.sol
81: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
174: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
321: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
File: contracts/p1/mixins/RewardableLib.sol
27: for (uint256 i = 0; i < registry.erc20s.length; ++i) {
Instances (16):
File: contracts/p1/AssetRegistry.sol
210: require(gas > GAS_TO_RESERVE, "not enough gas to unregister safely");
File: contracts/p1/BasketHandler.sol
198: require(0 < targetAmts[i], "invalid target amount; must be nonzero");
389: require(basketNonces.length == portions.length, "portions does not mirror basketNonces");
561: require(_targetAmts.length() == 0, "new basket missing target weights");
572: require(erc20s[i] != zero, "address zero is not valid collateral");
File: contracts/p1/RToken.sol
190: require(basketHandler.fullyCollateralized(), "partial redemption; use redeemCustom");
267: require(portionsSum == FIX_ONE, "portions do not add up to FIX_ONE");
File: contracts/p1/StRSR.sol
423: require(rsrAmount <= rsrBalance, "Cannot seize more RSR than we hold");
775: require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
790: require(from != address(0), "ERC20: transfer from the zero address");
791: require(to != address(0), "ERC20: transfer to the zero address");
795: require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
826: require(account != address(0), "ERC20: burn from the zero address");
832: require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
847: require(owner != address(0), "ERC20: approve from the zero address");
848: require(spender != address(0), "ERC20: approve to the zero address");
If a function modifier such as onlyOwner
is used, the function will revert if a normal user tries to pay the function. Marking the function as payable
will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided.
Instances (14):
File: contracts/mixins/Auth.sol
68: function __Auth_init(uint48 shortFreeze_, uint48 longFreeze_) internal onlyInitializing {
124: function freezeShort() external onlyRole(SHORT_FREEZER) {
139: function freezeLong() external onlyRole(LONG_FREEZER) {
152: function freezeForever() external onlyRole(OWNER) {
161: function unfreeze() external onlyRole(OWNER) {
169: function pauseTrading() external onlyRole(PAUSER) {
176: function unpauseTrading() external onlyRole(PAUSER) {
183: function pauseIssuance() external onlyRole(PAUSER) {
190: function unpauseIssuance() external onlyRole(PAUSER) {
198: function setShortFreeze(uint48 shortFreeze_) public onlyRole(OWNER) {
205: function setLongFreeze(uint48 longFreeze_) public onlyRole(OWNER) {
File: contracts/mixins/ComponentRegistry.sol
19: function __ComponentRegistry_init(Components memory components_) internal onlyInitializing {
File: contracts/p1/Main.sol
64: function _authorizeUpgrade(address newImplementation) internal override onlyRole(OWNER) {}
File: contracts/p1/mixins/Component.sol
33: function __Component_init(IMain main_) internal onlyInitializing {
Saves 5 gas per loop
Instances (11):
File: contracts/libraries/Fixed.sol
165: result++;
169: result++;
File: contracts/libraries/String.sol
14: for (uint256 i = 0; i < bStr.length; i++) {
File: contracts/p1/BasketHandler.sol
568: for (uint256 i = 0; i < erc20s.length; i++) {
File: contracts/p1/Distributor.sol
124: numTransfers++;
129: for (uint256 i = 0; i < numTransfers; i++) {
File: contracts/p1/StRSR.sol
640: era++;
652: draftEra++;
File: contracts/p1/mixins/BasketLib.sol
249: if (goodCollateral(targetNames.at(i), backup.erc20s[j], assetRegistry)) size++;
271: assigned++;
File: contracts/p1/mixins/Trading.sol
123: tradesOpen++;
If needed, the values can be read from the verified contract source code, or if there are multiple values there can be a single getter function that returns a tuple of the values of all currently-public constants. Saves 3406-3606 gas in deployment gas due to the compiler not having to create non-payable getter functions for deployment calldata, not having to store the bytes of the value outside of where it's used, and not adding another entry to the method ID table
Instances (36):
File: contracts/mixins/Auth.sol
29: bytes32 public constant OWNER_ROLE = OWNER;
30: bytes32 public constant SHORT_FREEZER_ROLE = SHORT_FREEZER;
31: bytes32 public constant LONG_FREEZER_ROLE = LONG_FREEZER;
32: bytes32 public constant PAUSER_ROLE = PAUSER;
File: contracts/p1/AssetRegistry.sol
15: uint256 public constant GAS_TO_RESERVE = 900000; // just enough to disable basket on n=128
File: contracts/p1/BackingManager.sol
33: uint48 public constant MAX_TRADING_DELAY = 31536000; // {s} 1 year
34: uint192 public constant MAX_BACKING_BUFFER = FIX_ONE; // {1} 100%
File: contracts/p1/BasketHandler.sol
27: uint192 public constant MAX_TARGET_AMT = 1e3 * FIX_ONE; // {target/BU} max basket weight
28: uint48 public constant MIN_WARMUP_PERIOD = 60; // {s} 1 minute
29: uint48 public constant MAX_WARMUP_PERIOD = 31536000; // {s} 1 year
File: contracts/p1/Broker.sol
25: uint48 public constant MAX_AUCTION_LENGTH = 604800; // {s} max valid duration - 1 week
26: uint48 public constant MIN_AUCTION_LENGTH = ONE_BLOCK * 2; // {s} min auction length - 2 blocks
File: contracts/p1/Deployer.sol
31: string public constant ENS = "reserveprotocol.eth";
File: contracts/p1/Distributor.sol
31: address public constant FURNACE = address(1);
32: address public constant ST_RSR = address(2);
34: uint8 public constant MAX_DESTINATIONS_ALLOWED = MAX_DESTINATIONS; // 100
File: contracts/p1/Furnace.sol
15: uint192 public constant MAX_RATIO = FIX_ONE; // {1} 100%
16: uint48 public constant PERIOD = ONE_BLOCK; // {s} 12 seconds; 1 block on PoS Ethereum
File: contracts/p1/RToken.sol
22: uint256 public constant MIN_THROTTLE_RATE_AMT = 1e18; // {qRTok}
23: uint256 public constant MAX_THROTTLE_RATE_AMT = 1e48; // {qRTok}
24: uint192 public constant MAX_THROTTLE_PCT_AMT = 1e18; // {qRTok}
25: uint192 public constant MIN_EXCHANGE_RATE = 1e9; // D18{BU/rTok}
26: uint192 public constant MAX_EXCHANGE_RATE = 1e27; // D18{BU/rTok}
File: contracts/p1/StRSR.sol
37: uint48 public constant PERIOD = ONE_BLOCK; // {s} 12 seconds; 1 block on PoS Ethereum
38: uint48 public constant MIN_UNSTAKING_DELAY = PERIOD * 2; // {s}
39: uint48 public constant MAX_UNSTAKING_DELAY = 31536000; // {s} 1 year
40: uint192 public constant MAX_REWARD_RATIO = FIX_ONE; // {1} 100%
46: uint8 public constant decimals = 18;
File: contracts/p1/mixins/Trading.sol
23: uint192 public constant MAX_TRADE_VOLUME = 1e29; // {UoA}
24: uint192 public constant MAX_TRADE_SLIPPAGE = 1e18; // {%}
File: contracts/plugins/governance/Governance.sol
31: uint256 public constant ONE_HUNDRED_PERCENT = 1e8; // {micro %}
File: contracts/plugins/trading/DutchTrade.sol
45: TradeKind public constant KIND = TradeKind.DUTCH_AUCTION;
File: contracts/plugins/trading/GnosisTrade.sol
20: TradeKind public constant KIND = TradeKind.BATCH_AUCTION;
21: uint256 public constant FEE_DENOMINATOR = 1000;
25: uint96 public constant MAX_ORDERS = 1e5;
28: uint192 public constant DEFAULT_MIN_BID = FIX_ONE / 100; // {tok}
Instances (5):
File: contracts/libraries/Fixed.sol
164: if (numerator % divisor > (divisor - 1) / 2) {
310: uint64 constant FIX_HALF = uint64(FIX_SCALE) / 2;
323: if (y & 1 == 1) result = (result * x + FIX_SCALE_SQ / 2) / FIX_SCALE_SQ;
326: x = (x * x + FIX_SCALE_SQ / 2) / FIX_SCALE_SQ;
591: if (mm > ((z - 1) / 2)) result += 1; // z should be z-1
Instances (10):
File: contracts/mixins/Auth.sol
199: require(shortFreeze_ > 0 && shortFreeze_ <= MAX_SHORT_FREEZE, "short freeze out of range");
206: require(longFreeze_ > 0 && longFreeze_ <= MAX_LONG_FREEZE, "long freeze out of range");
File: contracts/p1/BasketHandler.sol
493: require(val >= MIN_WARMUP_PERIOD && val <= MAX_WARMUP_PERIOD, "invalid warmupPeriod");
557: require(contains && amt >= newTargetAmts[i], "new basket adds target weights");
File: contracts/p1/Deployer.sol
110: require(owner != address(0) && owner != address(this), "invalid owner");
File: contracts/p1/RToken.sol
405: require(low >= MIN_EXCHANGE_RATE && high <= MAX_EXCHANGE_RATE, "BU rate out of range");
File: contracts/p1/RevenueTrader.sol
117: require(buyPrice > 0 && buyPrice < FIX_MAX, "buy asset price unknown");
File: contracts/p1/StRSR.sol
931: require(val > MIN_UNSTAKING_DELAY && val <= MAX_UNSTAKING_DELAY, "invalid unstakingDelay");
File: contracts/plugins/trading/DutchTrade.sol
116: require(sellLow > 0 && sellHigh < FIX_MAX, "bad sell pricing");
117: require(buyLow > 0 && buyHigh < FIX_MAX, "bad buy pricing");
Instances (63):
File: contracts/libraries/Fixed.sol
101: if (shiftLeft <= -96) return (rounding == CEIL ? 1 : 0); // 0 < uint.max / 10**77 < 0.5
102: if (40 <= shiftLeft) revert UIntOutOfBounds(); // 10**56 < FIX_MAX < 10**57
168: if (numerator % divisor > 0) {
589: if (mm > 0) result += 1;
File: contracts/libraries/Throttle.sol
52: if (amount > 0) {
File: contracts/mixins/Auth.sol
49: 0 <= longFreeze[a] <= LONG_FREEZE_CHARGES for all addrs a
199: require(shortFreeze_ > 0 && shortFreeze_ <= MAX_SHORT_FREEZE, "short freeze out of range");
206: require(longFreeze_ > 0 && longFreeze_ <= MAX_LONG_FREEZE, "long freeze out of range");
File: contracts/p1/AssetRegistry.sol
90: if (quantity > 0) basketHandler.disableBasket(); // not an interaction
107: if (quantity > 0) basketHandler.disableBasket(); // not an interaction
File: contracts/p1/BackingManager.sol
205: if (rsr.balanceOf(address(this)) > 0) {
241: if (totals.rsrTotal > 0) {
244: if (totals.rTokenTotal > 0) {
File: contracts/p1/BasketHandler.sol
177: require(erc20s.length > 0, "cannot empty basket");
182: if (config.erc20s.length > 0) requireConstantConfigTargets(erc20s, targetAmts);
198: require(0 < targetAmts[i], "invalid target amount; must be nonzero");
535: while (_targetAmts.length() > 0) {
File: contracts/p1/Broker.sol
188: require(batchAuctionLength > 0, "batch auctions not enabled");
212: require(dutchAuctionLength > 0, "dutch auctions not enabled");
File: contracts/p1/Distributor.sol
94: require(totalShares > 0, "nothing to distribute");
182: require(rTokenDist > 0 || rsrDist > 0, "no distribution defined");
182: require(rTokenDist > 0 || rsrDist > 0, "no distribution defined");
File: contracts/p1/Furnace.sol
79: if (amount > 0) rToken.melt(amount);
86: if (lastPayout > 0) try this.melt() {} catch {}
File: contracts/p1/RToken.sol
69: require(bytes(name_).length > 0, "name empty");
70: require(bytes(symbol_).length > 0, "symbol empty");
71: require(bytes(mandate_).length > 0, "mandate empty");
102: require(amount > 0, "Cannot issue zero");
131: uint192 amtBaskets = supply > 0
188: require(amount > 0, "Cannot redeem zero");
261: require(amount > 0, "Cannot redeem zero");
396: require(supply > 0, "0 supply");
478: uint256 amtRToken = totalSupply > 0
File: contracts/p1/RevenueTrader.sol
112: require(erc20.balanceOf(address(this)) > 0, "0 balance");
117: require(buyPrice > 0 && buyPrice < FIX_MAX, "buy asset price unknown");
File: contracts/p1/StRSR.sol
177: require(bytes(name_).length > 0, "name empty");
178: require(bytes(symbol_).length > 0, "symbol empty");
223: require(rsrAmount > 0, "Cannot stake zero");
257: require(stakeAmount > 0, "Cannot withdraw zero");
311: uint192 oldDrafts = firstId > 0 ? queue[firstId - 1].drafts : 0;
358: uint192 oldDrafts = firstId > 0 ? queue[firstId - 1].drafts : 0;
420: require(rsrAmount > 0, "Amount cannot be zero");
437: if (stakeRSR > 0) {
452: if (draftRSR > 0) {
621: uint192 oldDrafts = index > 0 ? queue[index - 1].drafts : 0;
622: uint64 lastAvailableAt = index > 0 ? queue[index - 1].availableAt : 0;
File: contracts/p1/StRSRVotes.sol
187: if (src != dst && amount > 0) {
218: if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) {
File: contracts/p1/mixins/BasketLib.sol
136: If unsoundPrimeWt(tgt) > 0 and len(backups(tgt)) == 0 for some tgt, then return false.
168: while (targetNames.length() > 0) targetNames.remove(targetNames.at(0));
279: return newBasket.erc20s.length > 0;
302: coll.refPerTok() > 0 &&
303: coll.targetPerRef() > 0;
File: contracts/p1/mixins/RecollateralizationLib.sol
405: high > 0 &&
File: contracts/p1/mixins/TradeLib.sol
52: assert(trade.buyPrice > 0 && trade.buyPrice < FIX_MAX && trade.sellPrice < FIX_MAX);
114: trade.sellPrice > 0 &&
116: trade.buyPrice > 0 &&
182: return size > 0 ? size : 1;
197: return size > 0 ? size : 1;
File: contracts/plugins/trading/DutchTrade.sol
116: require(sellLow > 0 && sellHigh < FIX_MAX, "bad sell pricing");
117: require(buyLow > 0 && buyHigh < FIX_MAX, "bad buy pricing");
File: contracts/plugins/trading/GnosisTrade.sol
185: if (sellBal > 0) IERC20Upgradeable(address(sell)).safeTransfer(origin, sellBal);
186: if (boughtAmt > 0) IERC20Upgradeable(address(buy)).safeTransfer(origin, boughtAmt);
If the functions are required by an interface, the contract should inherit from that interface and use the override
keyword
Instances (29):
File: contracts/interfaces/IAsset.sol
86: function worseThan(CollateralStatus a, CollateralStatus b) internal pure returns (bool) {
File: contracts/libraries/Array.sol
9: function allUnique(IERC20[] memory arr) internal pure returns (bool) {
21: function sortedAndAllUnique(IERC20[] memory arr) internal pure returns (bool) {
File: contracts/libraries/Fixed.sol
222: function plus(uint192 x, uint192 y) internal pure returns (uint192) {
229: function plusu(uint192 x, uint256 y) internal pure returns (uint192) {
236: function minus(uint192 x, uint192 y) internal pure returns (uint192) {
243: function minusu(uint192 x, uint256 y) internal pure returns (uint192) {
269: function mulu(uint192 x, uint256 y) internal pure returns (uint192) {
316: function powu(uint192 x_, uint48 y) internal pure returns (uint192) {
332: function lt(uint192 x, uint192 y) internal pure returns (bool) {
336: function lte(uint192 x, uint192 y) internal pure returns (bool) {
340: function gt(uint192 x, uint192 y) internal pure returns (bool) {
344: function gte(uint192 x, uint192 y) internal pure returns (bool) {
348: function eq(uint192 x, uint192 y) internal pure returns (bool) {
352: function neq(uint192 x, uint192 y) internal pure returns (bool) {
359: function near(
401: function mulu_toUint(uint192 x, uint256 y) internal pure returns (uint256) {
408: function mulu_toUint(
419: function mul_toUint(uint192 x, uint192 y) internal pure returns (uint256) {
426: function mul_toUint(
489: function safeMul(
File: contracts/libraries/Permit.sol
10: function requireSignature(
File: contracts/libraries/String.sol
11: function toLower(string memory str) internal pure returns (string memory) {
File: contracts/libraries/Throttle.sol
37: function useAvailable(
File: contracts/p1/mixins/BasketLib.sol
75: function setFrom(Basket storage self, Basket storage other) internal {
87: function add(
File: contracts/p1/mixins/RewardableLib.sol
25: function claimRewards(IAssetRegistry reg) internal {
38: function claimRewardsSingle(IAsset asset) internal {
File: contracts/p1/mixins/TradeLib.sol
108: function prepareTradeToCoverDeficit(
Issue | Instances | |
---|---|---|
NC-1 | require() / revert() statements should have descriptive reason strings |
1 |
NC-2 | Return values of approve() not checked |
5 |
NC-3 | Event is missing indexed fields |
11 |
NC-4 | Constants should be defined rather than using magic numbers | 5 |
NC-5 | Functions not used internally could be marked external | 84 |
Instances (1):
File: contracts/libraries/Fixed.sol
317: require(x_ <= FIX_ONE);
Not all IERC20 implementations revert()
when there's a failure in approve()
. The function signature has a boolean return value and they indicate errors that way instead. By not checking the return value, operations that should have marked as failed, may potentially go through without actually approving anything
Instances (5):
File: contracts/p1/StRSR.sol
748: _approve(_msgSender(), spender, amount);
768: _approve(owner, spender, _allowances[era][owner][spender] + addedValue);
777: _approve(owner, spender, currentAllowance - subtractedValue);
863: _approve(owner, spender, currentAllowance - amount);
898: _approve(owner, spender, value);
Index event fields make the field more quickly accessible to off-chain tools that parse events. However, note that each index field costs extra gas during emission, so it's not necessarily best to index the maximum allowed per event (three fields). Each event should use three indexed fields if there are three or more fields, and gas usage is not particularly of concern for the events in question. If there are fewer than three fields, all of the fields should be indexed.
Instances (11):
File: contracts/interfaces/IBasketHandler.sol
26: event PrimeBasketSet(IERC20[] erc20s, uint192[] targetAmts, bytes32[] targetNames);
33: event BasketSet(uint256 indexed nonce, IERC20[] erc20s, uint192[] refAmts, bool disabled);
39: event BackupConfigSet(bytes32 indexed targetName, uint256 indexed max, IERC20[] erc20s);
File: contracts/interfaces/IDeployerRegistry.sol
7: event DeploymentUnregistered(string version, IDeployer deployer);
8: event DeploymentRegistered(string version, IDeployer deployer);
9: event LatestChanged(string version, IDeployer deployer);
File: contracts/interfaces/IDistributor.sol
31: event DistributionSet(address dest, uint16 rTokenDist, uint16 rsrDist);
File: contracts/interfaces/IRToken.sol
48: event BasketsNeededChanged(uint192 oldBasketsNeeded, uint192 newBasketsNeeded);
52: event Melted(uint256 amount);
55: event IssuanceThrottleSet(ThrottleLib.Params oldVal, ThrottleLib.Params newVal);
58: event RedemptionThrottleSet(ThrottleLib.Params oldVal, ThrottleLib.Params newVal);
Instances (5):
File: contracts/libraries/Fixed.sol
102: if (40 <= shiftLeft) revert UIntOutOfBounds(); // 10**56 < FIX_MAX < 10**57
213: if (58 <= decimals) revert UIntOutOfBounds(); // 58, because x * 1e58 > 2 ** 192 if x != 0
390: if (96 <= decimals) revert UIntOutOfBounds();
File: contracts/plugins/trading/DutchTrade.sol
20: uint192 constant BASE = 999999e12; // {1} (999999/1000000)
57: uint48 public startTime; // {s} when the dutch auction begins (12s after init())
Instances (84):
File: contracts/libraries/test/ArrayCallerMock.sol
8: function allUnique(IERC20[] memory arr) public pure returns (bool) {
12: function sortedAndAllUnique(IERC20[] memory arr) public pure returns (bool) {
File: contracts/libraries/test/FixedCallerMock.sol
9: function toFix_(uint256 x) public pure returns (uint192 ) {
12: function shiftl_toFix_(uint256 x, int8 d) public pure returns (uint192 ) {
15: function shiftl_toFix_Rnd(uint256 x, int8 d, RoundingMode rnd) public pure returns (uint192 ) {
18: function divFix_(uint256 x, uint192 y) public pure returns (uint192 ) {
21: function divuu_(uint256 x, uint256 y) public pure returns (uint256) {
24: function fixMin_(uint192 x, uint192 y) public pure returns (uint192 ) {
27: function fixMax_(uint192 x, uint192 y) public pure returns (uint192 ) {
30: function abs_(int256 x) public pure returns (uint256) {
33: function divrnd_(uint256 n, uint256 d, RoundingMode rnd) public pure returns (uint256) {
36: function toUint(uint192 x) public pure returns (uint256 ) {
39: function toUintRnd(uint192 x, RoundingMode rnd) public pure returns (uint256 ) {
42: function shiftl(uint192 x, int8 decimals) public pure returns (uint192 ) {
45: function shiftlRnd(uint192 x, int8 decimals, RoundingMode rnd) public pure returns (uint192 ) {
48: function plus(uint192 x, uint192 y) public pure returns (uint192 ) {
51: function plusu(uint192 x, uint256 y) public pure returns (uint192 ) {
54: function minus(uint192 x, uint192 y) public pure returns (uint192 ) {
57: function minusu(uint192 x, uint256 y) public pure returns (uint192 ) {
60: function mul(uint192 x, uint192 y) public pure returns (uint192 ) {
63: function mulRnd(uint192 x, uint192 y, RoundingMode rnd) public pure returns (uint192 ) {
66: function mulu(uint192 x, uint256 y) public pure returns (uint192 ) {
69: function div(uint192 x, uint192 y) public pure returns (uint192 ) {
72: function divRnd(uint192 x, uint192 y, RoundingMode rnd) public pure returns (uint192 ) {
75: function divu(uint192 x, uint256 y) public pure returns (uint192 ) {
78: function divuRnd(uint192 x, uint256 y, RoundingMode rnd) public pure returns (uint192 ) {
81: function powu(uint192 x, uint48 y) public pure returns (uint192 ) {
84: function lt(uint192 x, uint192 y) public pure returns (bool) {
87: function lte(uint192 x, uint192 y) public pure returns (bool) {
90: function gt(uint192 x, uint192 y) public pure returns (bool) {
93: function gte(uint192 x, uint192 y) public pure returns (bool) {
96: function eq(uint192 x, uint192 y) public pure returns (bool) {
99: function neq(uint192 x, uint192 y) public pure returns (bool) {
102: function near(uint192 x, uint192 y, uint192 epsilon) public pure returns (bool) {
107: function shiftl_toUint(uint192 x, int8 d) public pure returns (uint256) {
110: function shiftl_toUintRnd(uint192 x, int8 d, RoundingMode rnd) public pure returns (uint256) {
113: function mulu_toUint(uint192 x, uint256 y) public pure returns (uint256) {
116: function mulu_toUintRnd(uint192 x, uint256 y, RoundingMode rnd) public pure returns (uint256) {
119: function mul_toUint(uint192 x, uint192 y) public pure returns (uint256) {
122: function mul_toUintRnd(uint192 x, uint192 y, RoundingMode rnd) public pure returns (uint256) {
125: function muluDivu(uint192 x, uint256 y, uint256 z) public pure returns (uint192 ) {
128: function muluDivuRnd(uint192 x, uint256 y, uint256 z, RoundingMode rnd) public pure returns (uint192 ) {
131: function mulDiv(uint192 x, uint192 y, uint192 z) public pure returns (uint192 ) {
134: function mulDivRnd(uint192 x, uint192 y, uint192 z, RoundingMode rnd) public pure returns (uint192 ) {
138: function safeMul_(uint192 a, uint192 b, RoundingMode rnd) public pure returns (uint192) {
143: function mulDiv256_(uint256 x, uint256 y, uint256 z) public pure returns (uint256) {
146: function mulDiv256Rnd_(uint256 x, uint256 y, uint256 z, RoundingMode rnd)
150: function fullMul_(uint256 x, uint256 y) public pure returns (uint256 h, uint256 l) {
File: contracts/mixins/Auth.sol
87: function grantRole(bytes32 role, address account)
99: function frozen() public view returns (bool) {
105: function tradingPausedOrFrozen() public view returns (bool) {
111: function issuancePausedOrFrozen() public view returns (bool) {
File: contracts/p1/AssetRegistry.sol
56: function refresh() public {
File: contracts/p1/BackingManager.sol
78: function settleTrade(IERC20 sell)
File: contracts/p1/BasketHandler.sol
287: function quantityUnsafe(IERC20 erc20, IAsset asset) public view returns (uint192) {
File: contracts/p1/Main.sol
53: function hasRole(bytes32 role, address account)
File: contracts/p1/RToken.sol
92: function issue(uint256 amount) public {
File: contracts/p1/RevenueTrader.sol
43: function settleTrade(IERC20 sell)
File: contracts/p1/StRSR.sol
222: function stake(uint256 rsrAmount) public {
719: function totalSupply() public view returns (uint256) {
723: function balanceOf(address account) public view returns (uint256) {
737: function transfer(address to, uint256 amount) public returns (bool) {
747: function approve(address spender, uint256 amount) public returns (bool) {
756: function transferFrom(
766: function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
772: function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
881: function permit(
901: function nonces(address owner) public view returns (uint256) {
905: function delegationNonces(address owner) public view returns (uint256) {
File: contracts/p1/StRSRVotes.sol
59: function checkpoints(address account, uint48 pos) public view returns (Checkpoint memory) {
63: function numCheckpoints(address account) public view returns (uint48) {
71: function getVotes(address account) public view returns (uint256) {
76: function getPastVotes(address account, uint256 blockNumber) public view returns (uint256) {
82: function getPastTotalSupply(uint256 blockNumber) public view returns (uint256) {
88: function getPastEra(uint256 blockNumber) public view returns (uint256) {
114: function delegate(address delegatee) public {
118: function delegateBySig(
File: contracts/plugins/governance/Governance.sol
51: function votingDelay() public view override(IGovernor, GovernorSettings) returns (uint256) {
55: function votingPeriod() public view override(IGovernor, GovernorSettings) returns (uint256) {
60: function proposalThreshold()
84: function state(uint256 proposalId)
93: function propose(
103: function queue(
161: function supportsInterface(bytes4 interfaceId)
Issue | Instances | |
---|---|---|
L-1 | Do not use deprecated library functions | 8 |
L-2 | Empty Function Body - Consider commenting why | 19 |
L-3 | Initializers could be front-run | 75 |
Instances (8):
File: contracts/p1/BackingManager.sol
69: IERC20(address(erc20)).safeApprove(address(main.rToken()), 0);
70: IERC20(address(erc20)).safeApprove(address(main.rToken()), type(uint256).max);
File: contracts/p1/RevenueTrader.sol
59: tokenToBuy.safeApprove(address(distributor), 0);
60: tokenToBuy.safeApprove(address(distributor), bal);
File: contracts/p1/mixins/Trading.sol
118: IERC20Upgradeable(address(sell)).safeApprove(address(broker), 0);
119: IERC20Upgradeable(address(sell)).safeApprove(address(broker), req.sellAmount);
File: contracts/plugins/trading/GnosisTrade.sol
130: IERC20Upgradeable(address(sell)).safeApprove(address(gnosis), 0);
131: IERC20Upgradeable(address(sell)).safeApprove(address(gnosis), initBal);
Instances (19):
File: contracts/p1/BackingManager.sol
89: try this.rebalance(trade.KIND()) {} catch (bytes memory errData) {
File: contracts/p1/Furnace.sol
86: if (lastPayout > 0) try this.melt() {} catch {}
86: if (lastPayout > 0) try this.melt() {} catch {}
File: contracts/p1/Main.sol
23: constructor() initializer {}
64: function _authorizeUpgrade(address newImplementation) internal override onlyRole(OWNER) {}
File: contracts/p1/RToken.sol
184: try main.furnace().melt() {} catch {} // nice for the redeemer, but not necessary
184: try main.furnace().melt() {} catch {} // nice for the redeemer, but not necessary
257: try main.furnace().melt() {} catch {}
257: try main.furnace().melt() {} catch {}
File: contracts/p1/StRSR.sol
705: function requireNotTradingPausedOrFrozen() private notTradingPausedOrFrozen {}
709: function requireNotFrozen() private notFrozen {}
713: function requireGovernanceOnly() private governance {}
File: contracts/p1/mixins/Component.sol
25: constructor() initializer {}
62: function _authorizeUpgrade(address newImplementation) internal view override governance {}
File: contracts/p1/mixins/RewardableLib.sol
30: try IRewardable(address(registry.erc20s[i])).claimRewards() {} catch {}
30: try IRewardable(address(registry.erc20s[i])).claimRewards() {} catch {}
41: try IRewardable(address(asset.erc20())).claimRewards() {} catch {}
41: try IRewardable(address(asset.erc20())).claimRewards() {} catch {}
File: contracts/plugins/governance/Governance.sol
47: {}
Initializers could be front-run, allowing an attacker to either set their own values, take ownership of the contract, and in the best case forcing a re-deployment
Instances (75):
File: contracts/interfaces/IAssetRegistry.sol
34: function init(IMain main_, IAsset[] memory assets_) external;
File: contracts/interfaces/IBackingManager.sol
29: function init(
File: contracts/interfaces/IBasketHandler.sol
55: function init(IMain main_, uint48 warmupPeriod_) external;
File: contracts/interfaces/IBroker.sol
36: function init(
File: contracts/interfaces/IDistributor.sol
40: function init(IMain main_, RevenueShare memory dist) external;
File: contracts/interfaces/IFurnace.sol
13: function init(IMain main_, uint192 ratio_) external;
File: contracts/interfaces/IMain.sol
173: function init(
File: contracts/interfaces/IRToken.sol
61: function init(
File: contracts/interfaces/IRevenueTrader.sol
16: function init(
File: contracts/interfaces/IStRSR.sol
101: function init(
File: contracts/interfaces/ITrade.sol
8: NOT_STARTED, // before init()
9: OPEN, // after init() and before settle()
12: PENDING // during init() or settle() (reentrancy protection)
File: contracts/mixins/Auth.sol
68: function __Auth_init(uint48 shortFreeze_, uint48 longFreeze_) internal onlyInitializing {
69: __AccessControl_init();
File: contracts/mixins/ComponentRegistry.sol
19: function __ComponentRegistry_init(Components memory components_) internal onlyInitializing {
File: contracts/p1/AssetRegistry.sol
41: function init(IMain main_, IAsset[] calldata assets_) external initializer {
41: function init(IMain main_, IAsset[] calldata assets_) external initializer {
42: __Component_init(main_);
File: contracts/p1/BackingManager.sol
46: function init(
52: ) external initializer {
53: __Component_init(main_);
54: __Trading_init(main_, maxTradeSlippage_, minTradeVolume_);
File: contracts/p1/BasketHandler.sol
92: function init(IMain main_, uint48 warmupPeriod_) external initializer {
92: function init(IMain main_, uint48 warmupPeriod_) external initializer {
93: __Component_init(main_);
File: contracts/p1/Broker.sol
63: function init(
70: ) external initializer {
71: __Component_init(main_);
207: trade.init(this, caller, gnosis, batchAuctionLength, req);
223: trade.init(caller, req.sell, req.buy, req.sellAmount, dutchAuctionLength);
File: contracts/p1/Deployer.sol
174: main.init(components, rsr, params.shortFreeze, params.longFreeze);
177: components.backingManager.init(
186: components.basketHandler.init(main, params.warmupPeriod);
189: components.rsrTrader.init(main, rsr, params.maxTradeSlippage, params.minTradeVolume);
190: components.rTokenTrader.init(
198: components.distributor.init(main, params.dist);
201: components.furnace.init(main, params.rewardRatio);
203: components.broker.init(
216: main.stRSR().init(
227: components.rToken.init(
242: components.assetRegistry.init(main, assets);
File: contracts/p1/Distributor.sol
41: function init(IMain main_, RevenueShare calldata dist) external initializer {
41: function init(IMain main_, RevenueShare calldata dist) external initializer {
42: __Component_init(main_);
File: contracts/p1/Furnace.sol
34: function init(IMain main_, uint192 ratio_) external initializer {
34: function init(IMain main_, uint192 ratio_) external initializer {
35: __Component_init(main_);
File: contracts/p1/Main.sol
23: constructor() initializer {}
26: function init(
31: ) public virtual initializer {
33: __Auth_init(shortFreeze_, longFreeze_);
34: __ComponentRegistry_init(components);
35: __UUPSUpgradeable_init();
File: contracts/p1/RToken.sol
61: function init(
68: ) external initializer {
72: __Component_init(main_);
73: __ERC20_init(name_, symbol_);
74: __ERC20Permit_init(name_);
File: contracts/p1/RevenueTrader.sol
26: function init(
31: ) external initializer {
33: __Component_init(main_);
34: __Trading_init(main_, maxTradeSlippage_, minTradeVolume_);
File: contracts/p1/StRSR.sol
169: function init(
176: ) external initializer {
179: __Component_init(main_);
180: __EIP712_init(name_, VERSION);
File: contracts/p1/mixins/Component.sol
25: constructor() initializer {}
33: function __Component_init(IMain main_) internal onlyInitializing {
35: __UUPSUpgradeable_init();
File: contracts/p1/mixins/Trading.sol
47: function __Trading_init(
File: contracts/plugins/trading/DutchTrade.sol
57: uint48 public startTime; // {s} when the dutch auction begins (12s after init())
100: function init(
File: contracts/plugins/trading/GnosisTrade.sol
45: uint256 public initBal; // {qTok}, this trade's balance of `sell` when init() was called
75: function init(
Issue | Instances | |
---|---|---|
M-1 | Centralization Risk for trusted owners | 18 |
Contracts have owners with privileged rights to perform admin tasks and need to be trusted to not perform malicious updates or drain funds.
Instances (18):
File: contracts/interfaces/IMain.sol
52: interface IAuth is IAccessControlUpgradeable {
166: interface IMain is IVersioned, IAuth, IComponentRegistry {
File: contracts/mixins/Auth.sol
16: abstract contract Auth is AccessControlUpgradeable, IAuth {
16: abstract contract Auth is AccessControlUpgradeable, IAuth {
90: onlyRole(getRoleAdmin(role))
124: function freezeShort() external onlyRole(SHORT_FREEZER) {
139: function freezeLong() external onlyRole(LONG_FREEZER) {
152: function freezeForever() external onlyRole(OWNER) {
161: function unfreeze() external onlyRole(OWNER) {
169: function pauseTrading() external onlyRole(PAUSER) {
176: function unpauseTrading() external onlyRole(PAUSER) {
183: function pauseIssuance() external onlyRole(PAUSER) {
190: function unpauseIssuance() external onlyRole(PAUSER) {
198: function setShortFreeze(uint48 shortFreeze_) public onlyRole(OWNER) {
205: function setLongFreeze(uint48 longFreeze_) public onlyRole(OWNER) {
File: contracts/mixins/ComponentRegistry.sol
13: abstract contract ComponentRegistry is Initializable, Auth, IComponentRegistry {
File: contracts/p1/Main.sol
18: contract MainP1 is Versioned, Initializable, Auth, ComponentRegistry, UUPSUpgradeable, IMain {
64: function _authorizeUpgrade(address newImplementation) internal override onlyRole(OWNER) {}
Acklowedged!