Platform: Code4rena
Start Date: 25/08/2022
Pot Size: $75,000 USDC
Total HM: 35
Participants: 147
Period: 7 days
Judge: 0xean
Total Solo HM: 15
Id: 156
League: ETH
Rank: 62/147
Findings: 2
Award: $91.18
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: zzzitron
Also found by: 0x040, 0x1f8b, 0x52, 0x85102, 0xDjango, 0xNazgul, 0xNineDec, 0xSky, 0xSmartContract, 0xkatana, 8olidity, Aymen0909, Bahurum, BipinSah, Bnke0x0, CRYP70, CertoraInc, Ch_301, Chandr, Chom, CodingNameKiki, Deivitto, DimSon, Diraco, ElKu, EthLedger, Funen, GalloDaSballo, Guardian, IllIllI, JansenC, Jeiwan, Lambda, LeoS, Margaret, MasterCookie, PPrieditis, PaludoX0, Picodes, PwnPatrol, RaymondFam, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, StevenL, The_GUILD, TomJ, Tomo, Trust, Waze, __141345__, ajtra, ak1, apostle0x01, aviggiano, bin2chen, bobirichman, brgltd, c3phas, cRat1st0s, carlitox477, cccz, ch13fd357r0y3r, cloudjunky, cryptphi, csanuragjain, d3e4, datapunk, delfin454000, devtooligan, dipp, djxploit, durianSausage, eierina, enckrish, erictee, fatherOfBlocks, gogo, grGred, hansfriese, hyh, ignacio, indijanc, itsmeSTYJ, ladboy233, lukris02, martin, medikko, mics, natzuu, ne0n, nxrblsrpr, okkothejawa, oyc_109, p_crypt0, pfapostol, prasantgupta52, rajatbeladiya, rbserver, reassor, ret2basic, robee, rokinot, rvierdiiev, shenwilly, sikorico, sorrynotsorry, tnevler, tonisives, w0Lfrum, yixxas
58.2885 DAI - $58.29
Avoid floating pragmas for non-library contracts.
While floating pragmas make sense for libraries to allow them to be included with multiple different versions of applications, it may be a security risk for application implementations.
A known vulnerable compiler version may accidentally be selected or security tools might fall-back to an older compiler version ending up checking a different EVM compilation that is ultimately deployed on the blockchain.
It is recommended to pin to a concrete compiler version.
2022-08-olympus/src/policies/interfaces/IHeart.sol::2 => pragma solidity >=0.8.0; 2022-08-olympus/src/policies/interfaces/IOperator.sol::2 => pragma solidity >=0.8.0;
Block timestamps have historically been used for a variety of applications, such as entropy for random numbers (see the Entropy Illusion for further details), locking funds for periods of time, and various state-changing conditional statements that are time-dependent. Miners have the ability to adjust timestamps slightly, which can prove to be dangerous if block timestamps are used incorrectly in smart contracts.
2022-08-olympus/src/modules/PRICE.sol::143 => lastObservationTime = uint48(block.timestamp); 2022-08-olympus/src/modules/PRICE.sol::146 => emit NewObservation(block.timestamp, currentPrice, _movingAverage); 2022-08-olympus/src/modules/PRICE.sol::165 => if (updatedAt < block.timestamp - 3 * uint256(observationFrequency)) 2022-08-olympus/src/modules/PRICE.sol::171 => if (updatedAt < block.timestamp - uint256(observationFrequency)) 2022-08-olympus/src/modules/PRICE.sol::215 => if (startObservations_.length != numObs || lastObservationTime_ > uint48(block.timestamp)) 2022-08-olympus/src/modules/RANGE.sol::85 => lastActive: uint48(block.timestamp), 2022-08-olympus/src/modules/RANGE.sol::92 => lastActive: uint48(block.timestamp), 2022-08-olympus/src/modules/RANGE.sol::136 => _range.high.lastActive = uint48(block.timestamp); 2022-08-olympus/src/modules/RANGE.sol::138 => emit WallDown(true, block.timestamp, capacity_); 2022-08-olympus/src/modules/RANGE.sol::148 => _range.low.lastActive = uint48(block.timestamp); 2022-08-olympus/src/modules/RANGE.sol::150 => emit WallDown(false, block.timestamp, capacity_); 2022-08-olympus/src/modules/RANGE.sol::191 => lastActive: uint48(block.timestamp), 2022-08-olympus/src/modules/RANGE.sol::200 => lastActive: uint48(block.timestamp), 2022-08-olympus/src/modules/RANGE.sol::207 => emit WallUp(high_, block.timestamp, capacity_); 2022-08-olympus/src/modules/RANGE.sol::231 => emit CushionDown(high_, block.timestamp); 2022-08-olympus/src/modules/RANGE.sol::233 => emit CushionUp(high_, block.timestamp, marketCapacity_); 2022-08-olympus/src/policies/Governance.sol::171 => block.timestamp, 2022-08-olympus/src/policies/Governance.sol::212 => if (block.timestamp > proposal.submissionTimestamp + ACTIVATION_DEADLINE) { 2022-08-olympus/src/policies/Governance.sol::227 => if (block.timestamp < activeProposal.activationTimestamp + GRACE_PERIOD) { 2022-08-olympus/src/policies/Governance.sol::231 => activeProposal = ActivatedProposal(proposalId_, block.timestamp); 2022-08-olympus/src/policies/Governance.sol::235 => emit ProposalActivated(proposalId_, block.timestamp); 2022-08-olympus/src/policies/Governance.sol::272 => if (block.timestamp < activeProposal.activationTimestamp + EXECUTION_TIMELOCK) { 2022-08-olympus/src/policies/Heart.sol::63 => lastBeat = block.timestamp; 2022-08-olympus/src/policies/Heart.sol::94 => if (block.timestamp < lastBeat + frequency()) revert Heart_OutOfCycle(); 2022-08-olympus/src/policies/Heart.sol::108 => emit Beat(block.timestamp); 2022-08-olympus/src/policies/Heart.sol::131 => lastBeat = block.timestamp - frequency(); 2022-08-olympus/src/policies/Operator.sol::128 => lastRegen: uint48(block.timestamp), 2022-08-olympus/src/policies/Operator.sol::210 => uint48(block.timestamp) >= RANGE.lastActive(true) + uint48(config_.regenWait) && 2022-08-olympus/src/policies/Operator.sol::216 => uint48(block.timestamp) >= RANGE.lastActive(false) + uint48(config_.regenWait) && 2022-08-olympus/src/policies/Operator.sol::404 => conclusion: uint48(block.timestamp + config_.cushionDuration), 2022-08-olympus/src/policies/Operator.sol::456 => conclusion: uint48(block.timestamp + config_.cushionDuration), 2022-08-olympus/src/policies/Operator.sol::708 => _status.high.lastRegen = uint48(block.timestamp); 2022-08-olympus/src/policies/Operator.sol::720 => _status.low.lastRegen = uint48(block.timestamp);
safeApprove() is deprecated in favor of safeIncreaseAllowance() and safeDecreaseAllowance(). If only setting the initial allowance to the value that means infinite, safeIncreaseAllowance() can be used instead
2022-08-olympus/src/policies/BondCallback.sol::57 => ohm.safeApprove(address(MINTR), type(uint256).max); 2022-08-olympus/src/policies/Operator.sol::167 => ohm.safeApprove(address(MINTR), type(uint256).max);
Code architecture, incentives, and error handling/reporting questions/issues should be resolved before deployment
2022-08-olympus/src/policies/Operator.sol::657 => /// TODO determine if this should use the last price from the MA or recalculate the current price, ideally last price is ok since it should have been just updated and should include check against secondary? 2022-08-olympus/src/policies/TreasuryCustodian.sol::51 => // TODO Currently allows anyone to revoke any approval EXCEPT activated policies. 2022-08-olympus/src/policies/TreasuryCustodian.sol::52 => // TODO must reorg policy storage to be able to check for deactivated policies. 2022-08-olympus/src/policies/TreasuryCustodian.sol::56 => // TODO Make sure `policy_` is an actual policy and not a random address.
decimals() is not part of the official ERC20 standard and might fail for tokens that do not implement it. While in practice it is very unlikely, as usually most of the tokens implement it, this should still be considered as a potential issue.
2022-08-olympus/src/modules/PRICE.sol::84 => uint8 ohmEthDecimals = _ohmEthPriceFeed.decimals(); 2022-08-olympus/src/modules/PRICE.sol::87 => uint8 reserveEthDecimals = _reserveEthPriceFeed.decimals(); 2022-08-olympus/src/policies/Operator.sol::122 => ohmDecimals = tokens_[0].decimals(); 2022-08-olympus/src/policies/Operator.sol::124 => reserveDecimals = tokens_[1].decimals(); 2022-08-olympus/src/policies/Operator.sol::375 => uint256 oracleScale = 10**uint8(int8(PRICE.decimals()) - priceDecimals); 2022-08-olympus/src/policies/Operator.sol::418 => uint8 oracleDecimals = PRICE.decimals(); 2022-08-olympus/src/policies/Operator.sol::493 => return decimals - int8(PRICE.decimals()); 2022-08-olympus/src/policies/Operator.sol::754 => 10**ohmDecimals * 10**PRICE.decimals() 2022-08-olympus/src/policies/Operator.sol::764 => 10**ohmDecimals * 10**PRICE.decimals(), 2022-08-olympus/src/policies/Operator.sol::784 => 10**ohmDecimals * 10**PRICE.decimals(),
Some tokens do not implement the ERC20 standard properly but are still accepted by most code that accepts ERC20 tokens. For example Tether (USDT)'s transfer() and transferFrom() functions do not return booleans as the specification requires, and instead have no return value. When these sorts of tokens are cast to IERC20, their function signatures do not match and therefore the calls made, revert. Use OpenZeppelin’s SafeERC20's safeTransfer()/safeTransferFrom() instead
2022-08-olympus/src/policies/Governance.sol::259 => VOTES.transferFrom(msg.sender, address(this), userVotes); 2022-08-olympus/src/policies/Governance.sol::312 => VOTES.transferFrom(address(this), msg.sender, userVotes);
When changing state variables events are not emitted. Emitting events allows monitoring activities with off-chain monitoring tools.
2022-08-olympus/src/Kernel.sol::126 => function setActiveStatus(bool activate_) external onlyKernel { 2022-08-olympus/src/policies/BondCallback.sol::190 => function setOperator(Operator operator_) external onlyRole("callback_admin") { 2022-08-olympus/src/policies/Operator.sol::498 => function setSpreads(uint256 cushionSpread_, uint256 wallSpread_) 2022-08-olympus/src/policies/Operator.sol::510 => function setThresholdFactor(uint256 thresholdFactor_) external onlyRole("operator_policy") { 2022-08-olympus/src/policies/Operator.sol::586 => function setBondContracts(IBondAuctioneer auctioneer_, IBondCallback callback_) 2022-08-olympus/src/policies/interfaces/IHeart.sol::34 => function setRewardTokenAndAmount(ERC20 token_, uint256 reward_) external; 2022-08-olympus/src/policies/interfaces/IOperator.sol::74 => function setSpreads(uint256 cushionSpread_, uint256 wallSpread_) external; 2022-08-olympus/src/policies/interfaces/IOperator.sol::80 => function setThresholdFactor(uint256 thresholdFactor_) external; 2022-08-olympus/src/policies/interfaces/IOperator.sol::85 => function setCushionFactor(uint32 cushionFactor_) external; 2022-08-olympus/src/policies/interfaces/IOperator.sol::92 => function setCushionParams( 2022-08-olympus/src/policies/interfaces/IOperator.sol::101 => function setReserveFactor(uint32 reserveFactor_) external; 2022-08-olympus/src/policies/interfaces/IOperator.sol::109 => function setRegenParams( 2022-08-olympus/src/policies/interfaces/IOperator.sol::119 => function setBondContracts(IBondAuctioneer auctioneer_, IBondCallback callback_) external;
Some tokens do not implement the ERC20 standard properly but are still accepted by most code that accepts ERC20 tokens. For example Tether (USDT)'s transfer() and transferFrom() functions do not return booleans as the specification requires, and instead have no return value. When these sorts of tokens are cast to IERC20, their function signatures do not match and therefore the calls made, revert. Use OpenZeppelin’s SafeERC20's safeTransfer()/safeTransferFrom() instead
2022-08-olympus/src/modules/VOTES.sol::36 => _mint(wallet_, amount_);
Some ERC20 tokens will revert when transferring zero. A require statement should be added to check that amount_
is not 0
https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/modules/TRSRY.sol#L82 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/modules/TRSRY.sol#L99 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/modules/TRSRY.sol#L110
https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/modules/MINTR.sol#L16 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/modules/RANGE.sol#L102-L103 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/modules/PRICE.sol#L83 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/modules/PRICE.sol#L86 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/policies/Operator.sol#L119-L121 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/policies/BondCallback.sol#L43-L44
Precision may be lost when casting uint48 to uint32
When getting prices using latestRoundData()
, roundID should also be validated against answeredInRound
eg
(uint80 roundID, int256 _price, , uint256 updatedAt, uint80 answeredInRound) = feed.latestRoundData(); require(answeredInRound >= roundID, "ChainLink: Stale price"); require(updatedAt != 0, "ChainLink: Round not complete");
https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/modules/PRICE.sol#L161 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/modules/PRICE.sol#L170
Use a solidity version of at least 0.8.4 to get bytes.concat() instead of abi.encodePacked(<bytes>,<bytes>) Use a solidity version of at least 0.8.12 to get string.concat() instead of abi.encodePacked(<str>,<str>) Use a solidity version of at least 0.8.13 to get the ability to use using for with a list of free functions
2022-08-olympus/src/policies/interfaces/IHeart.sol::2 => pragma solidity >=0.8.0; 2022-08-olympus/src/policies/interfaces/IOperator.sol::2 => pragma solidity >=0.8.0;
Use (e.g. 1e6) rather than decimal literals (e.g. 1000000), for better code readability
2022-08-olympus/src/modules/RANGE.sol::245 => wallSpread_ > 10000 || 2022-08-olympus/src/modules/RANGE.sol::247 => cushionSpread_ > 10000 || 2022-08-olympus/src/modules/RANGE.sol::264 => if (thresholdFactor_ > 10000 || thresholdFactor_ < 100) revert RANGE_InvalidParams(); 2022-08-olympus/src/policies/Governance.sol::164 => if (VOTES.balanceOf(msg.sender) * 10000 < VOTES.totalSupply() * SUBMISSION_REQUIREMENT) 2022-08-olympus/src/policies/Operator.sol::111 => if (configParams[4] > 10000 || configParams[4] < 100) revert Operator_InvalidParams(); 2022-08-olympus/src/policies/Operator.sol::518 => if (cushionFactor_ > 10000 || cushionFactor_ < 100) revert Operator_InvalidParams(); 2022-08-olympus/src/policies/Operator.sol::550 => if (reserveFactor_ > 10000 || reserveFactor_ < 100) revert Operator_InvalidParams();
Each event should use three indexed fields if there are three or more fields
2022-08-olympus/src/modules/INSTR.sol::11 => event InstructionsStored(uint256 instructionsId); 2022-08-olympus/src/modules/PRICE.sol::26 => event NewObservation(uint256 timestamp_, uint256 price_, uint256 movingAverage_); 2022-08-olympus/src/modules/PRICE.sol::27 => event MovingAverageDurationChanged(uint48 movingAverageDuration_); 2022-08-olympus/src/modules/PRICE.sol::28 => event ObservationFrequencyChanged(uint48 observationFrequency_); 2022-08-olympus/src/modules/RANGE.sol::20 => event WallUp(bool high_, uint256 timestamp_, uint256 capacity_); 2022-08-olympus/src/modules/RANGE.sol::21 => event WallDown(bool high_, uint256 timestamp_, uint256 capacity_); 2022-08-olympus/src/modules/RANGE.sol::22 => event CushionUp(bool high_, uint256 timestamp_, uint256 capacity_); 2022-08-olympus/src/modules/RANGE.sol::23 => event CushionDown(bool high_, uint256 timestamp_); 2022-08-olympus/src/modules/RANGE.sol::30 => event SpreadsChanged(uint256 cushionSpread_, uint256 wallSpread_); 2022-08-olympus/src/modules/RANGE.sol::31 => event ThresholdFactorChanged(uint256 thresholdFactor_); 2022-08-olympus/src/policies/Governance.sol::86 => event ProposalSubmitted(uint256 proposalId); 2022-08-olympus/src/policies/Governance.sol::87 => event ProposalEndorsed(uint256 proposalId, address voter, uint256 amount); 2022-08-olympus/src/policies/Governance.sol::88 => event ProposalActivated(uint256 proposalId, uint256 timestamp); 2022-08-olympus/src/policies/Governance.sol::89 => event WalletVoted(uint256 proposalId, address voter, bool for_, uint256 userVotes); 2022-08-olympus/src/policies/Governance.sol::90 => event ProposalExecuted(uint256 proposalId); 2022-08-olympus/src/policies/Heart.sol::28 => event Beat(uint256 timestamp_); 2022-08-olympus/src/policies/Heart.sol::29 => event RewardIssued(address to_, uint256 rewardAmount_); 2022-08-olympus/src/policies/Heart.sol::30 => event RewardUpdated(ERC20 token_, uint256 rewardAmount_); 2022-08-olympus/src/policies/Operator.sol::51 => event CushionFactorChanged(uint32 cushionFactor_); 2022-08-olympus/src/policies/Operator.sol::52 => event CushionParamsChanged(uint32 duration_, uint32 debtBuffer_, uint32 depositInterval_); 2022-08-olympus/src/policies/Operator.sol::53 => event ReserveFactorChanged(uint32 reserveFactor_); 2022-08-olympus/src/policies/Operator.sol::54 => event RegenParamsChanged(uint32 wait_, uint32 threshold_, uint32 observe_);
Code should include NatSpec
2022-08-olympus/src/policies/TreasuryCustodian.sol::1 => // SPDX-License-Identifier: AGPL-3.0 2022-08-olympus/src/utils/KernelUtils.sol::1 => // SPDX-License-Identifier: AGPL-3.0-only
It is bad practice to use numbers directly in code without explanation
2022-08-olympus/src/modules/PRICE.sol::90 => if (exponent > 38) revert Price_InvalidParams(); 2022-08-olympus/src/modules/RANGE.sol::245 => wallSpread_ > 10000 || 2022-08-olympus/src/modules/RANGE.sol::246 => wallSpread_ < 100 || 2022-08-olympus/src/modules/RANGE.sol::247 => cushionSpread_ > 10000 || 2022-08-olympus/src/modules/RANGE.sol::248 => cushionSpread_ < 100 || 2022-08-olympus/src/modules/RANGE.sol::264 => if (thresholdFactor_ > 10000 || thresholdFactor_ < 100) revert RANGE_InvalidParams(); 2022-08-olympus/src/policies/Governance.sol::164 => if (VOTES.balanceOf(msg.sender) * 10000 < VOTES.totalSupply() * SUBMISSION_REQUIREMENT) 2022-08-olympus/src/policies/Governance.sol::217 => (totalEndorsementsForProposal[proposalId_] * 100) < 2022-08-olympus/src/policies/Governance.sol::268 => if (netVotes * 100 < VOTES.totalSupply() * EXECUTION_THRESHOLD) { 2022-08-olympus/src/policies/Operator.sol::111 => if (configParams[4] > 10000 || configParams[4] < 100) revert Operator_InvalidParams(); 2022-08-olympus/src/policies/Operator.sol::378 => 36 + scaleAdjustment + int8(reserveDecimals) - int8(ohmDecimals) - priceDecimals 2022-08-olympus/src/policies/Operator.sol::433 => 36 + scaleAdjustment + int8(ohmDecimals) - int8(reserveDecimals) - priceDecimals 2022-08-olympus/src/policies/Operator.sol::518 => if (cushionFactor_ > 10000 || cushionFactor_ < 100) revert Operator_InvalidParams(); 2022-08-olympus/src/policies/Operator.sol::550 => if (reserveFactor_ > 10000 || reserveFactor_ < 100) revert Operator_InvalidParams(); 2022-08-olympus/src/utils/KernelUtils.sol::58 => for (uint256 i = 0; i < 32; ) {
Contracts are allowed to override their parents' functions and change the visibility from external to public.
2022-08-olympus/src/Kernel.sol::439 => function grantRole(Role role_, address addr_) public onlyAdmin { 2022-08-olympus/src/Kernel.sol::451 => function revokeRole(Role role_, address addr_) public onlyAdmin { 2022-08-olympus/src/modules/INSTR.sol::28 => function VERSION() public pure override returns (uint8 major, uint8 minor) { 2022-08-olympus/src/modules/INSTR.sol::37 => function getInstructions(uint256 instructionsId_) public view returns (Instruction[] memory) { 2022-08-olympus/src/modules/MINTR.sol::20 => function KEYCODE() public pure override returns (Keycode) { 2022-08-olympus/src/modules/MINTR.sol::33 => function mintOhm(address to_, uint256 amount_) public permissioned { 2022-08-olympus/src/modules/MINTR.sol::37 => function burnOhm(address from_, uint256 amount_) public permissioned { 2022-08-olympus/src/modules/PRICE.sol::108 => function KEYCODE() public pure override returns (Keycode) { 2022-08-olympus/src/modules/RANGE.sol::110 => function KEYCODE() public pure override returns (Keycode) { 2022-08-olympus/src/modules/TRSRY.sol::47 => function KEYCODE() public pure override returns (Keycode) { 2022-08-olympus/src/modules/VOTES.sol::22 => function KEYCODE() public pure override returns (Keycode) { 2022-08-olympus/src/modules/VOTES.sol::45 => function transfer(address to_, uint256 amount_) public pure override returns (bool) { 2022-08-olympus/src/policies/Governance.sol::145 => function getMetadata(uint256 proposalId_) public view returns (ProposalMetadata memory) { 2022-08-olympus/src/policies/Governance.sol::151 => function getActiveProposal() public view returns (ActivatedProposal memory) {
It is not necessary to have both a named return and a return statement.
2022-08-olympus/src/modules/INSTR.sol::28 => function VERSION() public pure override returns (uint8 major, uint8 minor) { 2022-08-olympus/src/modules/MINTR.sol::25 => function VERSION() external pure override returns (uint8 major, uint8 minor) { 2022-08-olympus/src/modules/PRICE.sol::113 => function VERSION() external pure override returns (uint8 major, uint8 minor) { 2022-08-olympus/src/modules/RANGE.sol::115 => function VERSION() external pure override returns (uint8 major, uint8 minor) { 2022-08-olympus/src/modules/TRSRY.sol::51 => function VERSION() external pure override returns (uint8 major, uint8 minor) { 2022-08-olympus/src/modules/VOTES.sol::27 => function VERSION() external pure override returns (uint8 major, uint8 minor) { 2022-08-olympus/src/policies/BondCallback.sol::177 => returns (uint256 in_, uint256 out_)
Emitting events after sensitive changes take place, to facilitate tracking and notify off-chain clients following changes to the contract.
2022-08-olympus/src/Kernel.sol::126 => function setActiveStatus(bool activate_) external onlyKernel { 2022-08-olympus/src/policies/BondCallback.sol::190 => function setOperator(Operator operator_) external onlyRole("callback_admin") { 2022-08-olympus/src/policies/Operator.sol::498 => function setSpreads(uint256 cushionSpread_, uint256 wallSpread_) 2022-08-olympus/src/policies/Operator.sol::510 => function setThresholdFactor(uint256 thresholdFactor_) external onlyRole("operator_policy") { 2022-08-olympus/src/policies/Operator.sol::586 => function setBondContracts(IBondAuctioneer auctioneer_, IBondCallback callback_) 2022-08-olympus/src/policies/interfaces/IHeart.sol::34 => function setRewardTokenAndAmount(ERC20 token_, uint256 reward_) external; 2022-08-olympus/src/policies/interfaces/IOperator.sol::74 => function setSpreads(uint256 cushionSpread_, uint256 wallSpread_) external; 2022-08-olympus/src/policies/interfaces/IOperator.sol::80 => function setThresholdFactor(uint256 thresholdFactor_) external; 2022-08-olympus/src/policies/interfaces/IOperator.sol::85 => function setCushionFactor(uint32 cushionFactor_) external; 2022-08-olympus/src/policies/interfaces/IOperator.sol::92 => function setCushionParams( 2022-08-olympus/src/policies/interfaces/IOperator.sol::101 => function setReserveFactor(uint32 reserveFactor_) external; 2022-08-olympus/src/policies/interfaces/IOperator.sol::109 => function setRegenParams( 2022-08-olympus/src/policies/interfaces/IOperator.sol::119 => function setBondContracts(IBondAuctioneer auctioneer_, IBondCallback callback_) external;
Usually lines in source code are limited to 80 characters. Today's screens are much larger so it's reasonable to stretch this in some cases. Since the files will most likely reside in GitHub, and GitHub starts using a scroll bar in all cases when the length is over 164 characters, the lines below should be split when they reach that length
2022-08-olympus/src/modules/PRICE.sol::31 => /// @dev Price feeds. Chainlink typically provides price feeds for an asset in ETH. Therefore, we use two price feeds against ETH, one for OHM and one for the Reserve asset, to calculate the relative price of OHM in the Reserve asset. 2022-08-olympus/src/modules/RANGE.sol::40 => uint256 spread; // Spread of the band (increase/decrease from the moving average to set the band prices), percent with 2 decimal places (i.e. 1000 = 10% spread) 2022-08-olympus/src/modules/RANGE.sol::46 => uint256 capacity; // Amount of tokens that can be used to defend the side of the range. Specified in OHM tokens on the high side and Reserve tokens on the low side. 2022-08-olympus/src/modules/RANGE.sol::61 => /// @notice Threshold factor for the change, a percent in 2 decimals (i.e. 1000 = 10%). Determines how much of the capacity must be spent before the side is taken down. 2022-08-olympus/src/policies/Operator.sol::97 => uint32[8] memory configParams // [cushionFactor, cushionDuration, cushionDebtBuffer, cushionDepositInterval, reserveFactor, regenWait, regenThreshold, regenObserve] 2022-08-olympus/src/policies/Operator.sol::657 => /// TODO determine if this should use the last price from the MA or recalculate the current price, ideally last price is ok since it should have been just updated and should include check against secondary? 2022-08-olympus/src/policies/interfaces/IOperator.sol::15 => uint32 cushionDebtBuffer; // Percentage over the initial debt to allow the market to accumulate at any one time. Percent with 3 decimals, e.g. 1_000 = 1 %. See IBondAuctioneer for more info. 2022-08-olympus/src/policies/interfaces/IOperator.sol::90 => /// @param debtBuffer_ - Percentage over the initial debt to allow the market to accumulate at any one time. Percent with 3 decimals, e.g. 1_000 = 1 %. See IBondAuctioneer for more info.
#0 - ind-igo
2022-09-09T04:04:17Z
Great report, thank you.
🌟 Selected for report: pfapostol
Also found by: 0x040, 0x1f8b, 0x85102, 0xDjango, 0xNazgul, 0xNineDec, 0xSmartContract, 0xkatana, Amithuddar, Aymen0909, Bnke0x0, CertoraInc, Chandr, CodingNameKiki, Deivitto, Dionysus, Diraco, ElKu, Fitraldys, Funen, GalloDaSballo, Guardian, IllIllI, JC, JansenC, Jeiwan, LeoS, Metatron, Noah3o6, RaymondFam, ReyAdmirado, Rohan16, RoiEvenHaim, Rolezn, Ruhum, Saintcode_, Shishigami, Sm4rty, SooYa, StevenL, Tagir2003, The_GUILD, TomJ, Tomo, Waze, __141345__, ajtra, apostle0x01, aviggiano, bobirichman, brgltd, c3phas, cRat1st0s, carlitox477, cccz, ch0bu, chrisdior4, d3e4, delfin454000, djxploit, durianSausage, erictee, exolorkistis, fatherOfBlocks, gogo, grGred, hyh, ignacio, jag, karanctf, kris, ladboy233, lukris02, m_Rassska, martin, medikko, natzuu, ne0n, newfork01, oyc_109, peiw, rbserver, ret2basic, robee, rokinot, rvierdiiev, sikorico, simon135, tnevler, zishansami
32.8928 DAI - $32.89
Uninitialized variables are assigned with the types default value. Explicitly initializing a variable with it's default value costs unnecesary gas.
2022-08-olympus/src/Kernel.sol::397 => for (uint256 i = 0; i < reqLength; ) { 2022-08-olympus/src/utils/KernelUtils.sol::43 => for (uint256 i = 0; i < 5; ) { 2022-08-olympus/src/utils/KernelUtils.sol::58 => for (uint256 i = 0; i < 32; ) {
Caching the array length outside a loop saves reading it on each iteration, as long as the array's length is not changed during the loop.
2022-08-olympus/src/policies/Governance.sol::278 => for (uint256 step; step < instructions.length; ) {
A division/multiplication by any number x being a power of 2 can be calculated by shifting log2(x) to the right/left.
While the DIV opcode uses 5 gas, the SHR opcode only uses 3 gas. Furthermore, Solidity's division operation also includes a division-by-0 prevention which is bypassed using shifting.
2022-08-olympus/src/policies/Operator.sol::372 => int8 scaleAdjustment = int8(ohmDecimals) - int8(reserveDecimals) + (priceDecimals / 2); 2022-08-olympus/src/policies/Operator.sol::419 => uint256 invCushionPrice = 10**(oracleDecimals * 2) / range.cushion.low.price; 2022-08-olympus/src/policies/Operator.sol::420 => uint256 invWallPrice = 10**(oracleDecimals * 2) / range.wall.low.price; 2022-08-olympus/src/policies/Operator.sol::427 => int8 scaleAdjustment = int8(reserveDecimals) - int8(ohmDecimals) + (priceDecimals / 2);
If needed, the value can be read from the verified contract source code. Savings are due to the compiler not having to create non-payable getter functions for deployment calldata, and not adding another entry to the method ID table
2022-08-olympus/src/modules/MINTR.sol::9 => OHM public immutable ohm; 2022-08-olympus/src/modules/RANGE.sol::68 => ERC20 public immutable ohm; 2022-08-olympus/src/modules/RANGE.sol::71 => ERC20 public immutable reserve; 2022-08-olympus/src/policies/Operator.sol::82 => ERC20 public immutable ohm; 2022-08-olympus/src/policies/Operator.sol::83 => uint8 public immutable ohmDecimals; 2022-08-olympus/src/policies/Operator.sol::85 => ERC20 public immutable reserve; 2022-08-olympus/src/policies/Operator.sol::86 => uint8 public immutable reserveDecimals;
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. The extra opcodes avoided are CALLVALUE(2),DUP1(3),ISZERO(3),PUSH2(3),JUMPI(10),PUSH1(3),DUP1(3),REVERT(0),JUMPDEST(1),POP(2), which costs an average of about 21 gas per call to the function, in addition to the extra deployment cost
2022-08-olympus/src/Kernel.sol::76 => function changeKernel(Kernel newKernel_) external onlyKernel { 2022-08-olympus/src/Kernel.sol::105 => function INIT() external virtual onlyKernel {} 2022-08-olympus/src/Kernel.sol::126 => function setActiveStatus(bool activate_) external onlyKernel { 2022-08-olympus/src/Kernel.sol::235 => function executeAction(Actions action_, address target_) external onlyExecutor { 2022-08-olympus/src/Kernel.sol::439 => function grantRole(Role role_, address addr_) public onlyAdmin { 2022-08-olympus/src/Kernel.sol::451 => function revokeRole(Role role_, address addr_) public onlyAdmin { 2022-08-olympus/src/policies/BondCallback.sol::152 => function batchToTreasury(ERC20[] memory tokens_) external onlyRole("callback_admin") { 2022-08-olympus/src/policies/BondCallback.sol::190 => function setOperator(Operator operator_) external onlyRole("callback_admin") { 2022-08-olympus/src/policies/Heart.sol::130 => function resetBeat() external onlyRole("heart_admin") { 2022-08-olympus/src/policies/Heart.sol::135 => function toggleBeat() external onlyRole("heart_admin") { 2022-08-olympus/src/policies/Heart.sol::150 => function withdrawUnspentRewards(ERC20 token_) external onlyRole("heart_admin") { 2022-08-olympus/src/policies/Operator.sol::195 => function operate() external override onlyWhileActive onlyRole("operator_operate") { 2022-08-olympus/src/policies/Operator.sol::510 => function setThresholdFactor(uint256 thresholdFactor_) external onlyRole("operator_policy") { 2022-08-olympus/src/policies/Operator.sol::516 => function setCushionFactor(uint32 cushionFactor_) external onlyRole("operator_policy") { 2022-08-olympus/src/policies/Operator.sol::548 => function setReserveFactor(uint32 reserveFactor_) external onlyRole("operator_policy") { 2022-08-olympus/src/policies/Operator.sol::618 => function regenerate(bool high_) external onlyRole("operator_admin") { 2022-08-olympus/src/policies/Operator.sol::624 => function toggleActive() external onlyRole("operator_admin") { 2022-08-olympus/src/policies/VoterRegistration.sol::45 => function issueVotesTo(address wallet_, uint256 amount_) external onlyRole("voter_admin") { 2022-08-olympus/src/policies/VoterRegistration.sol::53 => function revokeVotesFrom(address wallet_, uint256 amount_) external onlyRole("voter_admin") {
The code should be refactored such that they no longer exist, or the block should do something useful, such as emitting an event or reverting.
2022-08-olympus/src/Kernel.sol::85 => constructor(Kernel kernel_) KernelAdapter(kernel_) {} 2022-08-olympus/src/Kernel.sol::95 => function KEYCODE() public pure virtual returns (Keycode) {} 2022-08-olympus/src/Kernel.sol::100 => function VERSION() external pure virtual returns (uint8 major, uint8 minor) {} 2022-08-olympus/src/Kernel.sol::105 => function INIT() external virtual onlyKernel {} 2022-08-olympus/src/Kernel.sol::115 => constructor(Kernel kernel_) KernelAdapter(kernel_) {} 2022-08-olympus/src/Kernel.sol::139 => function configureDependencies() external virtual returns (Keycode[] memory dependencies) {} 2022-08-olympus/src/Kernel.sol::143 => function requestPermissions() external view virtual returns (Permissions[] memory requests) {} 2022-08-olympus/src/modules/INSTR.sol::20 => constructor(Kernel kernel_) Module(kernel_) {} 2022-08-olympus/src/modules/TRSRY.sol::45 => constructor(Kernel kernel_) Module(kernel_) {} 2022-08-olympus/src/modules/VOTES.sol::19 => {} 2022-08-olympus/src/policies/Governance.sol::59 => constructor(Kernel kernel_) Policy(kernel_) {} 2022-08-olympus/src/policies/PriceConfig.sol::15 => constructor(Kernel kernel_) Policy(kernel_) {} 2022-08-olympus/src/policies/TreasuryCustodian.sol::24 => constructor(Kernel kernel_) Policy(kernel_) {} 2022-08-olympus/src/policies/VoterRegistration.sol::16 => constructor(Kernel kernel_) Policy(kernel_) {}
When using elements that are smaller than 32 bytes, your contract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size.
2022-08-olympus/src/modules/PRICE.sol::44 => uint32 public nextObsIndex; 2022-08-olympus/src/modules/PRICE.sol::47 => uint32 public numObservations; 2022-08-olympus/src/modules/PRICE.sol::59 => uint8 public constant decimals = 18; 2022-08-olympus/src/modules/PRICE.sol::84 => uint8 ohmEthDecimals = _ohmEthPriceFeed.decimals(); 2022-08-olympus/src/modules/PRICE.sol::87 => uint8 reserveEthDecimals = _reserveEthPriceFeed.decimals(); 2022-08-olympus/src/modules/PRICE.sol::127 => uint32 numObs = numObservations; 2022-08-olympus/src/modules/PRICE.sol::185 => uint32 lastIndex = nextObsIndex == 0 ? numObservations - 1 : nextObsIndex - 1; 2022-08-olympus/src/policies/Operator.sol::83 => uint8 public immutable ohmDecimals; 2022-08-olympus/src/policies/Operator.sol::86 => uint8 public immutable reserveDecimals; 2022-08-olympus/src/policies/Operator.sol::89 => uint32 public constant FACTOR_SCALE = 1e4; 2022-08-olympus/src/policies/Operator.sol::485 => int8 decimals; 2022-08-olympus/src/policies/Operator.sol::665 => uint32 observe = _config.regenObserve; 2022-08-olympus/src/policies/interfaces/IOperator.sol::13 => uint32 cushionFactor; // percent of capacity to be used for a single cushion deployment, assumes 2 decimals (i.e. 1000 = 10%) 2022-08-olympus/src/policies/interfaces/IOperator.sol::14 => uint32 cushionDuration; // duration of a single cushion deployment in seconds 2022-08-olympus/src/policies/interfaces/IOperator.sol::15 => uint32 cushionDebtBuffer; // Percentage over the initial debt to allow the market to accumulate at any one time. Percent with 3 decimals, e.g. 1_000 = 1 %. See IBondAuctioneer for more info. 2022-08-olympus/src/policies/interfaces/IOperator.sol::16 => uint32 cushionDepositInterval; // Target frequency of deposits. Determines max payout of the bond market. See IBondAuctioneer for more info. 2022-08-olympus/src/policies/interfaces/IOperator.sol::17 => uint32 reserveFactor; // percent of reserves in treasury to be used for a single wall, assumes 2 decimals (i.e. 1000 = 10%) 2022-08-olympus/src/policies/interfaces/IOperator.sol::18 => uint32 regenWait; // minimum duration to wait to reinstate a wall in seconds 2022-08-olympus/src/policies/interfaces/IOperator.sol::19 => uint32 regenThreshold; // number of price points on other side of moving average to reinstate a wall 2022-08-olympus/src/policies/interfaces/IOperator.sol::20 => uint32 regenObserve; // number of price points to observe to determine regeneration 2022-08-olympus/src/policies/interfaces/IOperator.sol::31 => uint32 count; // current number of price points that count towards regeneration 2022-08-olympus/src/policies/interfaces/IOperator.sol::33 => uint32 nextObservation; // index of the next observation in the observations array
Booleans are more expensive than uint256 or any type that takes up a full word because each write operation emits an extra SLOAD to first read the slot's contents, replace the bits taken up by the boolean, and then write back. This is the compiler's defense against contract upgrades and pointer aliasing, and it cannot be disabled. Use uint256(1) and uint256(2) for true/false instead
2022-08-olympus/src/Kernel.sol::113 => bool public isActive; 2022-08-olympus/src/Kernel.sol::181 => mapping(Keycode => mapping(Policy => mapping(bytes4 => bool))) public modulePermissions; 2022-08-olympus/src/Kernel.sol::194 => mapping(address => mapping(Role => bool)) public hasRole; 2022-08-olympus/src/Kernel.sol::197 => mapping(Role => bool) public isRole; 2022-08-olympus/src/modules/PRICE.sol::62 => bool public initialized; 2022-08-olympus/src/policies/BondCallback.sol::24 => mapping(address => mapping(uint256 => bool)) public approvedMarkets; 2022-08-olympus/src/policies/Governance.sol::105 => mapping(uint256 => bool) public proposalHasBeenActivated; 2022-08-olympus/src/policies/Governance.sol::117 => mapping(uint256 => mapping(address => bool)) public tokenClaimsForProposal; 2022-08-olympus/src/policies/Heart.sol::33 => bool public active; 2022-08-olympus/src/policies/Operator.sol::63 => bool public initialized; 2022-08-olympus/src/policies/Operator.sol::66 => bool public active;
use <x> = <x> + <y> or <x> = <x> - <y> instead to save gas
2022-08-olympus/src/modules/PRICE.sol::136 => _movingAverage += (currentPrice - earliestPrice) / numObs; 2022-08-olympus/src/modules/PRICE.sol::138 => _movingAverage -= (earliestPrice - currentPrice) / numObs; 2022-08-olympus/src/modules/PRICE.sol::222 => total += startObservations_[i]; 2022-08-olympus/src/modules/TRSRY.sol::96 => reserveDebt[token_][msg.sender] += amount_; 2022-08-olympus/src/modules/TRSRY.sol::97 => totalDebt[token_] += amount_; 2022-08-olympus/src/modules/TRSRY.sol::115 => reserveDebt[token_][msg.sender] -= received; 2022-08-olympus/src/modules/TRSRY.sol::116 => totalDebt[token_] -= received; 2022-08-olympus/src/modules/TRSRY.sol::131 => if (oldDebt < amount_) totalDebt[token_] += amount_ - oldDebt; 2022-08-olympus/src/modules/TRSRY.sol::132 => else totalDebt[token_] -= oldDebt - amount_; 2022-08-olympus/src/modules/VOTES.sol::56 => balanceOf[from_] -= amount_; 2022-08-olympus/src/modules/VOTES.sol::58 => balanceOf[to_] += amount_; 2022-08-olympus/src/policies/BondCallback.sol::143 => _amountsPerMarket[id_][0] += inputAmount_; 2022-08-olympus/src/policies/BondCallback.sol::144 => _amountsPerMarket[id_][1] += outputAmount_; 2022-08-olympus/src/policies/Governance.sol::194 => totalEndorsementsForProposal[proposalId_] -= previousEndorsement; 2022-08-olympus/src/policies/Governance.sol::198 => totalEndorsementsForProposal[proposalId_] += userVotes; 2022-08-olympus/src/policies/Governance.sol::252 => yesVotesForProposal[activeProposal.proposalId] += userVotes; 2022-08-olympus/src/policies/Governance.sol::254 => noVotesForProposal[activeProposal.proposalId] += userVotes; 2022-08-olympus/src/policies/Heart.sol::103 => lastBeat += frequency();
Use a solidity version of at least 0.8.2 to get compiler automatic inlining Use a solidity version of at least 0.8.3 to get better struct packing and cheaper multiple storage reads Use a solidity version of at least 0.8.4 to get custom errors, which are cheaper at deployment than revert()/require() strings Use a solidity version of at least 0.8.10 to have external calls skip contract existence checks if the external call has a return value
2022-08-olympus/src/policies/interfaces/IHeart.sol::2 => pragma solidity >=0.8.0; 2022-08-olympus/src/policies/interfaces/IOperator.sol::2 => pragma solidity >=0.8.0;
++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too) Saves 5 gas PER LOOP
2022-08-olympus/src/utils/KernelUtils.sol::49 => i++; 2022-08-olympus/src/utils/KernelUtils.sol::64 => i++;
The extran comparison wastes gas if (<x> == true) => if (<x>), if (<x> == false) => if (!<x>)
2022-08-olympus/src/policies/Governance.sol::223 => if (proposalHasBeenActivated[proposalId_] == true) { 2022-08-olympus/src/policies/Governance.sol::306 => if (tokenClaimsForProposal[proposalId_][msg.sender] == true) {
Contracts are allowed to override their parents' functions and change the visibility from external to public and can save gas by doing so.
2022-08-olympus/src/Kernel.sol::439 => function grantRole(Role role_, address addr_) public onlyAdmin { 2022-08-olympus/src/Kernel.sol::451 => function revokeRole(Role role_, address addr_) public onlyAdmin { 2022-08-olympus/src/modules/INSTR.sol::28 => function VERSION() public pure override returns (uint8 major, uint8 minor) { 2022-08-olympus/src/modules/INSTR.sol::37 => function getInstructions(uint256 instructionsId_) public view returns (Instruction[] memory) { 2022-08-olympus/src/modules/MINTR.sol::20 => function KEYCODE() public pure override returns (Keycode) { 2022-08-olympus/src/modules/MINTR.sol::33 => function mintOhm(address to_, uint256 amount_) public permissioned { 2022-08-olympus/src/modules/MINTR.sol::37 => function burnOhm(address from_, uint256 amount_) public permissioned { 2022-08-olympus/src/modules/PRICE.sol::108 => function KEYCODE() public pure override returns (Keycode) { 2022-08-olympus/src/modules/RANGE.sol::110 => function KEYCODE() public pure override returns (Keycode) { 2022-08-olympus/src/modules/TRSRY.sol::47 => function KEYCODE() public pure override returns (Keycode) { 2022-08-olympus/src/modules/VOTES.sol::22 => function KEYCODE() public pure override returns (Keycode) { 2022-08-olympus/src/modules/VOTES.sol::45 => function transfer(address to_, uint256 amount_) public pure override returns (bool) { 2022-08-olympus/src/policies/Governance.sol::145 => function getMetadata(uint256 proposalId_) public view returns (ProposalMetadata memory) { 2022-08-olympus/src/policies/Governance.sol::151 => function getActiveProposal() public view returns (ActivatedProposal memory) {
It is not necessary to have both a named return and a return statement.
2022-08-olympus/src/modules/INSTR.sol::28 => function VERSION() public pure override returns (uint8 major, uint8 minor) { 2022-08-olympus/src/modules/MINTR.sol::25 => function VERSION() external pure override returns (uint8 major, uint8 minor) { 2022-08-olympus/src/modules/PRICE.sol::113 => function VERSION() external pure override returns (uint8 major, uint8 minor) { 2022-08-olympus/src/modules/RANGE.sol::115 => function VERSION() external pure override returns (uint8 major, uint8 minor) { 2022-08-olympus/src/modules/TRSRY.sol::51 => function VERSION() external pure override returns (uint8 major, uint8 minor) { 2022-08-olympus/src/modules/VOTES.sol::27 => function VERSION() external pure override returns (uint8 major, uint8 minor) { 2022-08-olympus/src/policies/BondCallback.sol::177 => returns (uint256 in_, uint256 out_)
Saves a storage slot for the mapping. Depending on the circumstances and sizes of types, can avoid a Gsset (20000 gas) per mapping combined. Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot. Finally, if both fields are accessed in the same function, can save ~42 gas per access due to not having to recalculate the key's keccak256 hash (Gkeccak256 - 30 gas) and that calculation's associated stack operations.
2022-08-olympus/src/modules/TRSRY.sol::33 => mapping(address => mapping(ERC20 => uint256)) public withdrawApproval; 2022-08-olympus/src/modules/TRSRY.sol::39 => mapping(ERC20 => mapping(address => uint256)) public reserveDebt;
2022-08-olympus/src/policies/Governance.sol::102 => mapping(uint256 => mapping(address => uint256)) public userEndorsementsForProposal; 2022-08-olympus/src/policies/Governance.sol::114 => mapping(uint256 => mapping(address => uint256)) public userVotesForProposal; 2022-08-olympus/src/policies/Governance.sol::117 => mapping(uint256 => mapping(address => bool)) public tokenClaimsForProposal;
Saves 6 gas per instance if using assembly to check for address(0)
e.g.
assembly { if iszero(_addr) { mstore(0x00, "zero address") revert(0x00, 0x20) } }
instances:
2022-08-olympus/src/Kernel.sol::269 => if (address(getModuleForKeycode[keycode]) != address(0))
When fetching data from a storage location, assigning the data to a memory variable causes all fields of the struct/array to be read from storage, which incurs a Gcoldsload (2100 gas) for each field of the struct/array. If the fields are read from the new memory variable, they incur an additional MLOAD rather than a cheap stack read.
Instead of declearing the variable with the memory keyword, declaring the variable with the storage keyword and caching any fields that need to be re-read in stack variables, will be much cheaper, only incuring the Gcoldsload for the fields actually read. The only time it makes sense to read the whole struct/array into a memory variable, is if the full struct/array is being returned by the function, is being passed to a function that requires memory, or if the array/struct is being read from another memory array/struct
2022-08-olympus/src/Kernel.sol::379 => Policy[] memory dependents = moduleDependents[keycode_];
Not inlining costs 20 to 40 gas because of two extra JUMP instructions and additional stack operations needed for function calls.
2022-08-olympus/src/Kernel.sol::131 => function getModuleAddress(Keycode keycode_) internal view returns (address) { 2022-08-olympus/src/Kernel.sol::266 => function _installModule(Module newModule_) internal { 2022-08-olympus/src/Kernel.sol::279 => function _upgradeModule(Module newModule_) internal { 2022-08-olympus/src/Kernel.sol::295 => function _activatePolicy(Policy policy_) internal { 2022-08-olympus/src/Kernel.sol::325 => function _deactivatePolicy(Policy policy_) internal { 2022-08-olympus/src/Kernel.sol::351 => function _migrateKernel(Kernel newKernel_) internal { 2022-08-olympus/src/Kernel.sol::378 => function _reconfigurePolicies(Keycode keycode_) internal { 2022-08-olympus/src/Kernel.sol::409 => function _pruneFromDependents(Policy policy_) internal { 2022-08-olympus/src/policies/Heart.sol::111 => function _issueReward(address to_) internal { 2022-08-olympus/src/policies/Operator.sol::652 => function _addObservation() internal {
Avoids a Gsset (20000 gas) in the constructor, and replaces each Gwarmacces (100 gas) with a PUSH32 (3 gas).
2022-08-olympus/src/policies/BondCallback.sol::43 => aggregator = aggregator_; 2022-08-olympus/src/policies/BondCallback.sol::44 => ohm = ohm_; 2022-08-olympus/src/policies/Heart.sol::60 => _operator = operator_; 2022-08-olympus/src/policies/Operator.sol::144 => _status = Status({low: regen, high: regen});
If the functions are required by an interface, the contract should inherit from that interface and use the override keyword
2022-08-olympus/src/Kernel.sol::131 => function getModuleAddress(Keycode keycode_) internal view returns (address) {