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
Rank: 47/127
Findings: 3
Award: $56.12
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: rbserver
Also found by: 0x1f8b, 0xNazgul, 0xc0ffEE, 8olidity, Aymen0909, Chom, Franfran, Jeiwan, Jujic, Lambda, M4TZ1P, Olivierdem, Rolezn, Ruhum, TomJ, Wawrdog, __141345__, bin2chen, c7e7eff, carlitox477, catchup, cccz, codexploder, cuteboiz, d3e4, dipp, djxploit, eierina, elprofesor, hansfriese, horsefacts, idkwhatimdoing, imare, immeas, joestakey, ladboy233, leosathya, martin, minhtrng, pashov, peanuts, pedroais, rokinot, rvierdiiev, saneryee, sorrynotsorry, tonisives
0.385 USDC - $0.38
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
Price can be stale and can lead to wrong price
return value.
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
🌟 Selected for report: 0x1f8b
Also found by: 0xNazgul, 0xSmartContract, Aymen0909, B2, Bnke0x0, Deivitto, Diana, Dinesh11G, ElKu, JC, Josiah, Rahoz, RaymondFam, ReyAdmirado, Rolezn, Waze, __141345__, adriro, aphak5010, brgltd, c3phas, c7e7eff, carlitox477, cducrest, ch0bu, chrisdior4, cryptonue, cryptostellar5, cylzxje, d3e4, delfin454000, enckrish, evmwanderer, fatherOfBlocks, gogo, hansfriese, horsefacts, immeas, leosathya, lukris02, neumo, oyc_109, pedr02b2, rbserver, robee, rotcivegaf, rvierdiiev, sakshamguruji, shark, simon135, tnevler, trustindistrust, wagmi
36.7345 USDC - $36.73
Issue | Contexts | |
---|---|---|
LOW‑1 | Missing Checks for Address(0x0) | 33 |
LOW‑2 | IERC20 approve() Is Deprecated | 1 |
LOW‑3 | The Contract Should approve(0) First | 1 |
LOW‑4 | Missing parameter validation in constructor | 15 |
Total: 50 contexts over 4 issues
Issue | Contexts | |
---|---|---|
NC‑1 | Critical Changes Should Use Two-step Procedure | 17 |
NC‑2 | Public Functions Not Called By The Contract Should Be Declared External Instead | 40 |
NC‑3 | Missing event for critical parameter change | 19 |
NC‑4 | require() / revert() Statements Should Have Descriptive Reason Strings | 3 |
NC‑5 | Implementation contract may not be initialized | 4 |
NC‑6 | Avoid Floating Pragmas: The Version Should Be Locked | All in-scope contracts |
NC‑7 | Use of ecrecover is susceptible to signature malleability | 3 |
Total: 94 contexts over 7 issues
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.
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
Consider adding explicit zero-address validation on input parameters of address type.
approve()
Is Deprecatedapprove()
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-
50: _token.approve(address(xINV), type(uint).max);
https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/INVEscrow.sol#L50
Consider using safeIncreaseAllowance()
/ safeDecreaseAllowance()
instead.
approve(0)
FirstSome 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.
50: _token.approve(address(xINV), type(uint).max);
https://github.com/code-423n4/2022-10-inverse/tree/main/src/escrows/INVEscrow.sol#L50
Approve with a zero amount first before setting the actual amount.
constructor
Some parameters of constructors are not checked for invalid values.
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
Validate the parameters.
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
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
Lack of two-step procedure for critical operations leaves them error-prone. Consider adding two step procedure on the critical functions.
Contracts are allowed to override their parents’ functions and change the visibility from external to public.
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
When changing state variables events are not emitted. Emitting events allows monitoring activities with off-chain monitoring tools.
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
require()
/ revert()
Statements Should Have Descriptive Reason Strings93: 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
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
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
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.
All in-scope contracts use floating pragmas ^0.8.13 of Solidity
pragma solidity ^0.8.13;
ecrecover
is susceptible to signature malleabilityThe 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.
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
🌟 Selected for report: pfapostol
Also found by: 0x1f8b, 0xRoxas, 0xSmartContract, Amithuddar, Aymen0909, B2, Bnke0x0, Chandr, CloudX, Deivitto, Diana, Dinesh11G, ElKu, HardlyCodeMan, JC, JrNet, KoKo, Mathieu, Ozy42, Rahoz, RaymondFam, ReyAdmirado, Rolezn, Shinchan, __141345__, adriro, ajtra, aphak5010, ballx, c3phas, carlitox477, ch0bu, chaduke, cryptostellar5, djxploit, durianSausage, enckrish, exolorkistis, fatherOfBlocks, gogo, horsefacts, kaden, karanctf, leosathya, martin, mcwildy, oyc_109, ret2basic, robee, sakman, sakshamguruji, shark, skyle, tnevler
19.0072 USDC - $19.01
Issue | Contexts | |
---|---|---|
GAS‑1 | Multiple Address Mappings Can Be Combined Into A Single Mapping Of An Address To A Struct, Where Appropriate | 3 |
GAS‑2 | require() /revert() Strings Longer Than 32 Bytes Cost Extra Gas | 12 |
GAS‑3 | Using > 0 Costs More Gas Than != 0 When Used On A Uint In A require() Statement | 11 |
GAS‑4 | Splitting require() Statements That Use && Saves Gas | 8 |
GAS‑5 | abi.encode() Is Less Efficient Than abi.encodepacked() | 5 |
GAS‑6 | Don’t Compare Boolean Expressions To Boolean Literals | 1 |
GAS‑7 | Public Functions To External | 80 |
GAS‑8 | Usage of uints /ints smaller than 32 bytes (256 bits) incurs overhead | 14 |
GAS‑9 | Optimize names to save gas | All in-scope contracts |
GAS‑10 | Use uint256(1) /uint256(2) instead for true and false boolean states | 8 |
GAS‑11 | Can use constant instead of immutable | 1 |
Total: 244 contexts over 14 issues
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.
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
require()
/revert()
Strings Longer Than 32 Bytes Cost Extra Gas63: 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
> 0
costs more gas than != 0
when used on a uint
in a require()
statementThis change saves 6 gas per instance
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
require()
Statements That Use &&
Saves GasSee 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
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
abi.encode()
is less efficient than abi.encodepacked()
See for more information: https://github.com/ConnorBlockchain/Solidity-Encode-Gas-Comparison
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
For cases of: if (<x> == true)
, use if (<x>)
instead
For cases of: if (<x> == false)
, use if (!<x>)
instead
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
The following functions could be set external to save gas and improve code quality. External call cost is less expensive than of public functions.
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
uints
/ints
smaller than 32 bytes (256 bits) incurs overheadWhen 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
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
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
Relevant to all in-scope contracts
uint256(1)
/uint256(2)
instead for true
and false
boolean statesIf 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.
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
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