Inverse Finance contest - Rolezn's results

Rethink the way you borrow.

General Information

Platform: Code4rena

Start Date: 25/10/2022

Pot Size: $50,000 USDC

Total HM: 18

Participants: 127

Period: 5 days

Judge: 0xean

Total Solo HM: 9

Id: 175

League: ETH

Inverse Finance

Findings Distribution

Researcher Performance

Rank: 47/127

Findings: 3

Award: $56.12

QA:
grade-b
Gas:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L83 https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L116

Vulnerability details

Description

Price can be stale and can lead to wrong price return value.

Proof of Concept

Oracle data feed is insufficiently validated. There is no check for stale price and round completeness. Price can be stale and can lead to wrong answer return value.

uint price = feeds[token].feed.latestAnswer();

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L83

uint price = feeds[token].feed.latestAnswer();

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L116

Use latestRoundData and validate data feed

(uint80 roundID, int256 price, , uint256 timestamp, uint80 priceInRound) = feeds[token].feed.latestRoundData(); require(price > 0, "Invalid feed price"); require(priceInRound >= roundID, "stale price"); require(timestamp > 0, "round not complete");

#0 - c4-judge

2022-11-05T21:13:21Z

0xean marked the issue as duplicate

#1 - Simon-Busch

2022-12-05T15:26:58Z

Issue marked as satisfactory as requested by 0xean

#2 - c4-judge

2022-12-07T08:14:13Z

Simon-Busch marked the issue as duplicate of #584

Summary<a name="Summary">

Low Risk Issues

IssueContexts
LOW‑1Missing Checks for Address(0x0)33
LOW‑2IERC20 approve() Is Deprecated1
LOW‑3The Contract Should approve(0) First1
LOW‑4Missing parameter validation in constructor15

Total: 50 contexts over 4 issues

Non-critical Issues

IssueContexts
NC‑1Critical Changes Should Use Two-step Procedure17
NC‑2Public Functions Not Called By The Contract Should Be Declared External Instead40
NC‑3Missing event for critical parameter change19
NC‑4require() / revert() Statements Should Have Descriptive Reason Strings3
NC‑5Implementation contract may not be initialized4
NC‑6Avoid Floating Pragmas: The Version Should Be LockedAll in-scope contracts
NC‑7Use of ecrecover is susceptible to signature malleability3

Total: 94 contexts over 7 issues

Low Risk Issues

<a href="#Summary">[LOW‑1]</a><a name="LOW&#x2011;1"> Missing Checks for Address(0x0)

Lack of zero-address validation on address parameters may lead to transaction reverts, waste gas, require resubmission of transactions and may even force contract redeployments in certain cases within the protocol.

<ins>Proof Of Concept</ins>
26: function setOperator: address _operator

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L26

32: function allow: address allowedContract

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L32

38: function deny: address deniedContract

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L38

53: function setPendingOperator: address newOperator_

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L53

81: function addMinter: address minter_

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L81

90: function removeMinter: address minter_

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L90

99: function addMarket: address market_

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L99

284: function accrueDueTokens: address user

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L284

313: function onRepay: address user

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L313

325: function onForceReplenish: address user

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L325

349: function mint: address to

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L349

48: function changeGov: address _gov

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L48

66: function changeChair: address _chair

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L66

130: function setGov: address _gov

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L130

136: function setLender: address _lender

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L136

142: function setPauseGuardian: address _pauseGuardian

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L142

278: function deposit: address user

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L278

422: function borrowOnBehalf: address from

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L422

486: function withdrawOnBehalf: address from

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L486

531: function repay: address user

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L531

559: function forceReplenish: address user

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L559

591: function liquidate: address user

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L591

44: function setPendingOperator: address newOperator_

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L44

53: function setFeed: address token

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L53

61: function setFixedPrice: address token

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L61

112: function getPrice: address token

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L112

30: function initialize: address _beneficiary

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/GovTokenEscrow.sol#L30

43: function pay: address recipient

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/GovTokenEscrow.sol#L43

66: function delegate: address delegatee

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/GovTokenEscrow.sol#L66

44: function initialize: address _beneficiary

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/INVEscrow.sol#L44

59: function pay: address recipient

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/INVEscrow.sol#L59

90: function delegate: address delegatee

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/INVEscrow.sol#L90

36: function pay: address recipient

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/SimpleERC20Escrow.sol#L36

<ins>Recommended Mitigation Steps</ins>

Consider adding explicit zero-address validation on input parameters of address type.

<a href="#Summary">[LOW‑2]</a><a name="LOW&#x2011;2"> IERC20 approve() Is Deprecated

approve() is subject to a known front-running attack. It 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.

https://docs.openzeppelin.com/contracts/3.x/api/token/erc20#IERC20-approve-address-uint256-

<ins>Proof Of Concept</ins>
50: _token.approve(address(xINV), type(uint).max);

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/INVEscrow.sol#L50

<ins>Recommended Mitigation Steps</ins>

Consider using safeIncreaseAllowance() / safeDecreaseAllowance() instead.

<a href="#Summary">[LOW‑3]</a><a name="LOW&#x2011;3"> The Contract Should approve(0) First

Some tokens (like USDT L199) do not work when changing the allowance from an existing non-zero allowance value. They must first be approved by zero and then the actual allowance must be approved.

<ins>Proof Of Concept</ins>
50: _token.approve(address(xINV), type(uint).max);

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/INVEscrow.sol#L50

<ins>Recommended Mitigation Steps</ins>

Approve with a zero amount first before setting the actual amount.

<a href="#Summary">[LOW‑4]</a><a name="LOW&#x2011;4"> Missing parameter validation in constructor

Some parameters of constructors are not checked for invalid values.

<ins>Proof Of Concept</ins>
14: operator = _operator;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L14

36: replenishmentPriceBps = _replenishmentPriceBps; 37: name = _name; 38: symbol = _symbol; 39: operator = _operator;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L36-L39

39: gov = _gov; 40: chair = _chair; 41: supplyCeiling = _supplyCeiling;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L39-L41

77: gov = _gov; 78: lender = _lender; 79: pauseGuardian = _pauseGuardian; 80: escrowImplementation = _escrowImplementation; 84: collateralFactorBps = _collateralFactorBps; 86: liquidationIncentiveBps = _liquidationIncentiveBps;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L77-L86

32: operator = _operator;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L32

<ins>Recommended Mitigation Steps</ins>

Validate the parameters.

Non Critical Issues

<a href="#Summary">[NC‑1]</a><a name="NC&#x2011;1"> Critical Changes Should Use Two-step Procedure

The critical procedures should be two step process.

See similar findings in previous Code4rena contests for reference: https://code4rena.com/reports/2022-06-illuminate/#2-critical-changes-should-use-two-step-procedure

<ins>Proof Of Concept</ins>
26: function setOperator(address _operator) public onlyOperator { operator = _operator; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L26

62: function setReplenishmentPriceBps(uint newReplenishmentPriceBps_) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L62

48: function changeGov(address _gov) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L48

57: function changeSupplyCeiling(uint _supplyCeiling) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L57

66: function changeChair(address _chair) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L66

118: function setOracle(IOracle _oracle) public onlyGov { oracle = _oracle; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L118

124: function setBorrowController(IBorrowController _borrowController) public onlyGov { borrowController = _borrowController; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L124

130: function setGov(address _gov) public onlyGov { gov = _gov; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L130

136: function setLender(address _lender) public onlyGov { lender = _lender; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L136

142: function setPauseGuardian(address _pauseGuardian) public onlyGov { pauseGuardian = _pauseGuardian; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L142

149: function setCollateralFactorBps(uint _collateralFactorBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L149

161: function setLiquidationFactorBps(uint _liquidationFactorBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L161

172: function setReplenismentIncentiveBps(uint _replenishmentIncentiveBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L172

183: function setLiquidationIncentiveBps(uint _liquidationIncentiveBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L183

194: function setLiquidationFeeBps(uint _liquidationFeeBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L194

53: function setFeed(address token, IChainlinkFeed feed, uint8 tokenDecimals) public onlyOperator { feeds[token] = FeedData(feed, tokenDecimals); }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L53

61: function setFixedPrice(address token, uint price) public onlyOperator { fixedPrices[token] = price; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L61

<ins>Recommended Mitigation Steps</ins>

Lack of two-step procedure for critical operations leaves them error-prone. Consider adding two step procedure on the critical functions.

<a href="#Summary">[NC‑2]</a><a name="NC&#x2011;2"> Public Functions Not Called By The Contract Should Be Declared External Instead

Contracts are allowed to override their parents’ functions and change the visibility from external to public.

<ins>Proof Of Concept</ins>
function setOperator(address _operator) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L26

function allow(address allowedContract) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L32

function deny(address deniedContract) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L38

function setReplenishmentPriceBps(uint newReplenishmentPriceBps_) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L62

function addMinter(address minter_) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L81

function removeMinter(address minter_) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L90

function addMarket(address market_) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L99

function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L215

function accrueDueTokens(address user) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L284

function changeGov(address _gov) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L48

function changeSupplyCeiling(uint _supplyCeiling) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L57

function changeChair(address _chair) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L66

function resign() public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L75

function expansion(IMarket market, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L86

function contraction(IMarket market, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L103

function takeProfit(IMarket market) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L131

function setOracle(IOracle _oracle) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L118

function setBorrowController(IBorrowController _borrowController) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L124

function setGov(address _gov) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L130

function setLender(address _lender) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L136

function setPauseGuardian(address _pauseGuardian) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L142

function setCollateralFactorBps(uint _collateralFactorBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L149

function setLiquidationFactorBps(uint _liquidationFactorBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L161

function setReplenismentIncentiveBps(uint _replenishmentIncentiveBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L172

function setLiquidationIncentiveBps(uint _liquidationIncentiveBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L183

function setLiquidationFeeBps(uint _liquidationFeeBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L194

function pauseBorrows(bool _value) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L212

function deposit(uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L258

function depositAndBorrow(uint amountDeposit, uint amountBorrow) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L267

function deposit(address user, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L278

function borrow(uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L408

function borrowOnBehalf(address from, uint amount, uint deadline, uint8 v, bytes32 r, bytes32 s) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L422

function withdraw(uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L472

function withdrawOnBehalf(address from, uint amount, uint deadline, uint8 v, bytes32 r, bytes32 s) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L486

function repay(address user, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L531

function repayAndWithdraw(uint repayAmount, uint withdrawAmount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L546

function forceReplenish(address user, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L559

function liquidate(address user, uint repaidDebt) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L591

function setFeed(address token, IChainlinkFeed feed, uint8 tokenDecimals) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L53

function setFixedPrice(address token, uint price) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L61

<a href="#Summary">[NC‑3]</a><a name="NC&#x2011;3"> Missing event for critical parameter change

When changing state variables events are not emitted. Emitting events allows monitoring activities with off-chain monitoring tools.

<ins>Proof Of Concept</ins>
26: function setOperator(address _operator) public onlyOperator { operator = _operator; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L26

53: function setPendingOperator(address newOperator_) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L53

62: function setReplenishmentPriceBps(uint newReplenishmentPriceBps_) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L62

48: function changeGov(address _gov) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L48

57: function changeSupplyCeiling(uint _supplyCeiling) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L57

66: function changeChair(address _chair) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L66

118: function setOracle(IOracle _oracle) public onlyGov { oracle = _oracle; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L118

124: function setBorrowController(IBorrowController _borrowController) public onlyGov { borrowController = _borrowController; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L124

130: function setGov(address _gov) public onlyGov { gov = _gov; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L130

136: function setLender(address _lender) public onlyGov { lender = _lender; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L136

142: function setPauseGuardian(address _pauseGuardian) public onlyGov { pauseGuardian = _pauseGuardian; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L142

149: function setCollateralFactorBps(uint _collateralFactorBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L149

161: function setLiquidationFactorBps(uint _liquidationFactorBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L161

172: function setReplenismentIncentiveBps(uint _replenishmentIncentiveBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L172

183: function setLiquidationIncentiveBps(uint _liquidationIncentiveBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L183

194: function setLiquidationFeeBps(uint _liquidationFeeBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L194

44: function setPendingOperator(address newOperator_) public onlyOperator { pendingOperator = newOperator_; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L44

53: function setFeed(address token, IChainlinkFeed feed, uint8 tokenDecimals) public onlyOperator { feeds[token] = FeedData(feed, tokenDecimals); }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L53

61: function setFixedPrice(address token, uint price) public onlyOperator { fixedPrices[token] = price; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L61

<a href="#Summary">[NC‑4]</a><a name="NC&#x2011;4"> require() / revert() Statements Should Have Descriptive Reason Strings

<ins>Proof Of Concept</ins>
93: require(globalSupply <= supplyCeiling);

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L93

67: require(msg.sender == beneficiary);

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/GovTokenEscrow.sol#L67

91: require(msg.sender == beneficiary);

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/INVEscrow.sol#L91

<a href="#Summary">[NC‑5]</a><a name="NC&#x2011;5"> Implementation contract may not be initialized

OpenZeppelin recommends that the initializer modifier be applied to constructors. Per OZs Post implementation contract should be initialized to avoid potential griefs or exploits. https://forum.openzeppelin.com/t/uupsupgradeable-vulnerability-post-mortem/15680/5

<ins>Proof Of Concept</ins>
13: constructor(address _operator) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L13

30: constructor( 31: uint _replenishmentPriceBps, 32: string memory _name, 33: string memory _symbol, 34: address _operator 35: ) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L30-L35

29: constructor( 30: address _operator 31: ) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L29-L31

34: constructor(IXINV _xINV) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/INVEscrow.sol#L34

<a href="#Summary">[NC‑6]</a><a name="NC&#x2011;6"> Avoid Floating Pragmas: The Version Should Be Locked

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.

<ins>Proof Of Concept</ins>

All in-scope contracts use floating pragmas ^0.8.13 of Solidity

pragma solidity ^0.8.13;

<a href="#Summary">[NC‑7]</a><a name="NC&#x2011;7"> Use of ecrecover is susceptible to signature malleability

The built-in EVM precompile ecrecover is susceptible to signature malleability, which could lead to replay attacks. References: https://swcregistry.io/docs/SWC-117, https://swcregistry.io/docs/SWC-121, and https://medium.com/cryptronics/signature-replay-vulnerabilities-in-smart-contracts-3b6f7596df57. While this is not immediately exploitable, this may become a vulnerability if used elsewhere.

<ins>Proof Of Concept</ins>
226: address recoveredAddress = ecrecover(

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L226

425: address recoveredAddress = ecrecover(

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L425

489: address recoveredAddress = ecrecover(

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L489

Consider using OpenZeppelin’s ECDSA library (which prevents this malleability) instead of the built-in function. https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol

#0 - c4-judge

2022-11-07T21:19:27Z

0xean marked the issue as grade-b

Summary<a name="Summary">

Gas Optimizations

IssueContexts
GAS‑1Multiple Address Mappings Can Be Combined Into A Single Mapping Of An Address To A Struct, Where Appropriate3
GAS‑2require()/revert() Strings Longer Than 32 Bytes Cost Extra Gas12
GAS‑3Using > 0 Costs More Gas Than != 0 When Used On A Uint In A require() Statement11
GAS‑4Splitting require() Statements That Use && Saves Gas8
GAS‑5abi.encode() Is Less Efficient Than abi.encodepacked()5
GAS‑6Don’t Compare Boolean Expressions To Boolean Literals1
GAS‑7Public Functions To External80
GAS‑8Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead14
GAS‑9Optimize names to save gasAll in-scope contracts
GAS‑10Use uint256(1)/uint256(2) instead for true and false boolean states8
GAS‑11Can use constant instead of immutable1

Total: 244 contexts over 14 issues

Gas Optimizations

<a href="#Summary">[GAS‑1]</a><a name="GAS&#x2011;1"> Multiple Address Mappings Can Be Combined Into A Single Mapping Of An Address To A Struct, Where Appropriate

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.

<ins>Proof Of Concept</ins>
19: mapping(address => uint256) public balances; 20: mapping(address => mapping(address => uint256)) public allowance; 23: mapping(address => uint256) public nonces;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L19-L23

<a href="#Summary">[GAS‑2]</a><a name="GAS&#x2011;2"> require()/revert() Strings Longer Than 32 Bytes Cost Extra Gas

<ins>Proof Of Concept</ins>
63: require(newReplenishmentPriceBps_ > 0, "replenishment price must be over 0");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L63

301: require(markets[msg.sender], "Only markets can call onBorrow");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L301

314: require(markets[msg.sender], "Only markets can call onRepay");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L314

326: require(markets[msg.sender], "Only markets can call onForceReplenish");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L326

89: require(market.borrowPaused() != true, "CANNOT EXPAND PAUSED MARKETS");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L89

75: require(_liquidationIncentiveBps > 0 && _liquidationIncentiveBps < 10000, "Invalid liquidation incentive"); 76: require(_replenishmentIncentiveBps < 10000, "Replenishment incentive must be less than 100%");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L75-L76

93: require(msg.sender == gov, "Only gov can call this function");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L93

173: require(_replenishmentIncentiveBps > 0 && _replenishmentIncentiveBps < 10000, "Invalid replenishment incentive");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L173

184: require(_liquidationIncentiveBps > 0 && _liquidationIncentiveBps + liquidationFeeBps < 10000, "Invalid liquidation incentive");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L184

214: require(msg.sender == pauseGuardian || msg.sender == gov, "Only pause guardian or governance can pause");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L214

462: require(limit >= amount, "Insufficient withdrawal limit");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L462

<a href="#Summary">[GAS‑3]</a><a name="GAS&#x2011;3"> Using > 0 costs more gas than != 0 when used on a uint in a require() statement

This change saves 6 gas per instance

<ins>Proof Of Concept</ins>
63: require(newReplenishmentPriceBps_ > 0, "replenishment price must be over 0");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L63

328: require(deficit > 0, "No deficit");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L328

75: require(_liquidationIncentiveBps > 0 && _liquidationIncentiveBps < 10000, "Invalid liquidation incentive");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L75

162: require(_liquidationFactorBps > 0 && _liquidationFactorBps <= 10000, "Invalid liquidation factor");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L162

173: require(_replenishmentIncentiveBps > 0 && _replenishmentIncentiveBps < 10000, "Invalid replenishment incentive");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L173

184: require(_liquidationIncentiveBps > 0 && _liquidationIncentiveBps + liquidationFeeBps < 10000, "Invalid liquidation incentive");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L184

195: require(_liquidationFeeBps > 0 && _liquidationFeeBps + liquidationIncentiveBps < 10000, "Invalid liquidation fee");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L195

561: require(deficit > 0, "No DBR deficit");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L561

592: require(repaidDebt > 0, "Must repay positive debt");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L592

83: require(price > 0, "Invalid feed price");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L83

117: require(price > 0, "Invalid feed price");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L117

<a href="#Summary">[GAS‑4]</a><a name="GAS&#x2011;4"> Splitting require() Statements That Use && Saves Gas

See https://github.com/code-423n4/2022-01-xdefi-findings/issues/128 which describes the fact that there is a larger deployment gas cost, but with enough runtime calls, the change ends up being cheaper

<ins>Proof Of Concept</ins>
249: require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L249

75: require(_liquidationIncentiveBps > 0 && _liquidationIncentiveBps < 10000, "Invalid liquidation incentive");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L75

162: require(_liquidationFactorBps > 0 && _liquidationFactorBps <= 10000, "Invalid liquidation factor");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L162

173: require(_replenishmentIncentiveBps > 0 && _replenishmentIncentiveBps < 10000, "Invalid replenishment incentive");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L173

184: require(_liquidationIncentiveBps > 0 && _liquidationIncentiveBps + liquidationFeeBps < 10000, "Invalid liquidation incentive");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L184

195: require(_liquidationFeeBps > 0 && _liquidationFeeBps + liquidationIncentiveBps < 10000, "Invalid liquidation fee");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L195

448: require(recoveredAddress != address(0) && recoveredAddress == from, "INVALID_SIGNER");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L448

512: require(recoveredAddress != address(0) && recoveredAddress == from, "INVALID_SIGNER");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L512

<a href="#Summary">[GAS‑5]</a><a name="GAS&#x2011;5"> abi.encode() is less efficient than abi.encodepacked()

See for more information: https://github.com/ConnorBlockchain/Solidity-Encode-Gas-Comparison

<ins>Proof Of Concept</ins>
232: abi.encode(

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L232

269: abi.encode(

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L269

104: abi.encode(

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L104

431: abi.encode(

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L431

495: abi.encode(

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L495

<a href="#Summary">[GAS‑6]</a><a name="GAS&#x2011;6"> Don't compare boolean expressions to boolean literals

For cases of: if (<x> == true), use if (<x>) instead For cases of: if (<x> == false), use if (!<x>) instead

<ins>Proof Of Concept</ins>
350: require(minters[msg.sender] == true || msg.sender == operator, "ONLY MINTERS OR OPERATOR");

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L350

<a href="#Summary">[GAS‑7]</a><a name="GAS&#x2011;7"> Public Functions To External

The following functions could be set external to save gas and improve code quality. External call cost is less expensive than of public functions.

<ins>Proof Of Concept</ins>
function setOperator(address _operator) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L26

function allow(address allowedContract) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L32

function deny(address deniedContract) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L38

function borrowAllowed(address msgSender, address, uint) public view returns (bool) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L46

function setPendingOperator(address newOperator_) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L53

function setReplenishmentPriceBps(uint newReplenishmentPriceBps_) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L62

function claimOperator() public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L70

function addMinter(address minter_) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L81

function removeMinter(address minter_) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L90

function addMarket(address market_) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L99

function totalSupply() public view returns (uint) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L109

function balanceOf(address user) public view returns (uint) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L120

function deficitOf(address user) public view returns (uint) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L133

function signedBalanceOf(address user) public view returns (int) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L146

function approve(address spender, uint256 amount) public virtual returns (bool) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L158

function transfer(address to, uint256 amount) public virtual returns (bool) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L170

function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L188

function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L215

function invalidateNonce() public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L258

function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L262

function accrueDueTokens(address user) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L284

function onBorrow(address user, uint additionalDebt) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L300

function onRepay(address user, uint repaidDebt) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L313

function onForceReplenish(address user, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L325

function burn(uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L340

function mint(address to, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L349

function changeGov(address _gov) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L48

function changeSupplyCeiling(uint _supplyCeiling) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L57

function changeChair(address _chair) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L66

function resign() public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L75

function expansion(IMarket market, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L86

function contraction(IMarket market, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L103

function getProfit(IMarket market) public view returns (uint) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L120

function takeProfit(IMarket market) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Fed.sol#L131

function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L97

function setOracle(IOracle _oracle) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L118

function setBorrowController(IBorrowController _borrowController) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L124

function setGov(address _gov) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L130

function setLender(address _lender) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L136

function setPauseGuardian(address _pauseGuardian) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L142

function setCollateralFactorBps(uint _collateralFactorBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L149

function setLiquidationFactorBps(uint _liquidationFactorBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L161

function setReplenismentIncentiveBps(uint _replenishmentIncentiveBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L172

function setLiquidationIncentiveBps(uint _liquidationIncentiveBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L183

function setLiquidationFeeBps(uint _liquidationFeeBps) public onlyGov {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L194

function recall(uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L203

function pauseBorrows(bool _value) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L212

function deposit(uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L258

function depositAndBorrow(uint amountDeposit, uint amountBorrow) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L267

function deposit(address user, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L278

function predictEscrow(address user) public view returns (IEscrow predicted) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L292

function getCollateralValue(address user) public view returns (uint) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L312

function getCreditLimit(address user) public view returns (uint) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L334

function getWithdrawalLimit(address user) public view returns (uint) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L370

function borrow(uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L408

function borrowOnBehalf(address from, uint amount, uint deadline, uint8 v, bytes32 r, bytes32 s) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L422

function withdraw(uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L472

function withdrawOnBehalf(address from, uint amount, uint deadline, uint8 v, bytes32 r, bytes32 s) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L486

function invalidateNonce() public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L520

function repay(address user, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L531

function repayAndWithdraw(uint repayAmount, uint withdrawAmount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L546

function forceReplenish(address user, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L559

function getLiquidatableDebt(address user) public view returns (uint) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L578

function liquidate(address user, uint repaidDebt) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Market.sol#L591

function setPendingOperator(address newOperator_) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L44

function setFeed(address token, IChainlinkFeed feed, uint8 tokenDecimals) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L53

function setFixedPrice(address token, uint price) public onlyOperator {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L61

function claimOperator() public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L66

function initialize(IERC20 _token, address _beneficiary) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/GovTokenEscrow.sol#L30

function pay(address recipient, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/GovTokenEscrow.sol#L43

function balance() public view returns (uint) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/GovTokenEscrow.sol#L52

function delegate(address delegatee) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/GovTokenEscrow.sol#L9

function initialize(IERC20 _token, address _beneficiary) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/INVEscrow.sol#L44

function pay(address recipient, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/INVEscrow.sol#L59

function balance() public view returns (uint) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/INVEscrow.sol#L70

function onDeposit() public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/INVEscrow.sol#L79

function delegate(address delegatee) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/INVEscrow.sol#L10

function initialize(IERC20 _token, address) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/SimpleERC20Escrow.sol#L25

function pay(address recipient, uint amount) public {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/SimpleERC20Escrow.sol#L36

function balance() public view returns (uint) {

https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/SimpleERC20Escrow.sol#L45

<a href="#Summary">[GAS‑8]</a><a name="GAS&#x2011;8"> Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead

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.

https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html Each operation involving a uint8 costs an extra 22-28 gas (depending on whether the other operand is also a variable of type uint8) as compared to ones involving uint256, due to the compiler having to clear the higher bits of the memory word before operating on the uint8, as well as the associated stack operations of doing so. Use a larger size then downcast where needed

<ins>Proof Of Concept</ins>
13: uint8 public constant decimals = 18;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L13

20: uint8 tokenDecimals;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L20

85: uint8 feedDecimals = feeds[token].feed.decimals();

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L85

119: uint8 feedDecimals = feeds[token].feed.decimals();

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L119

86: uint8 tokenDecimals = feeds[token].tokenDecimals;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L86

120: uint8 tokenDecimals = feeds[token].tokenDecimals;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L120

87: uint8 decimals = 36 - feedDecimals - tokenDecimals;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L87

121: uint8 decimals = 36 - feedDecimals - tokenDecimals;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/Oracle.sol#L121

<a href="#Summary">[GAS‑9]</a><a name="GAS&#x2011;9"> Optimize names to save gas

public/external function names and public member variable names can be optimized to save gas. See this link for an example of how it works. Method IDs that have two leading zero bytes can save 128 gas each during deployment, and renaming functions to have lower method IDs will save 22 gas per call, per sorted position shifted

<ins>Proof Of Concept</ins>

Relevant to all in-scope contracts

<a href="#Summary">[GAS‑10]</a><a name="GAS&#x2011;10"> Use uint256(1)/uint256(2) instead for true and false boolean states

If you don't use boolean for storage you will avoid Gwarmaccess 100 gas. In addition, state changes of boolean from true to false can cost up to ~20000 gas rather than uint256(2) to uint256(1) that would cost significantly less.

<ins>Proof Of Concept</ins>
11: mapping(address => bool) public contractAllowlist;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L11

32: function allow(address allowedContract) public onlyOperator { contractAllowlist[allowedContract] = true; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L32

38: function deny(address deniedContract) public onlyOperator { contractAllowlist[deniedContract] = false; }

https://github.com/code-423n4/2022-10-inverse/tree/main/src/BorrowController.sol#L38

24: mapping (address => bool) public minters;. 25: mapping (address => bool) public markets;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L24-L25

82: minters[minter_] = true;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L82

91: minters[minter_] = false;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L91

100: markets[market_] = true;

https://github.com/code-423n4/2022-10-inverse/tree/main/src/DBR.sol#L100

<a href="#Summary">[GAS‑11]</a><a name="GAS&#x2011;11"> Can use constant instead of immutable

No other changes are performed on the dola variable, as a result this can be set from immutable to constant. See more at: https://docs.soliditylang.org/en/v0.8.13/contracts.html#constant-and-immutable-state-variables

IERC20 public immutable dola = IERC20(0x865377367054516e17014CcdED1e7d814EDC9ce4);

#0 - c4-judge

2022-11-05T23:44:11Z

0xean marked the issue as grade-b

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter