Inverse Finance contest - durianSausage'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: 98/127

Findings: 1

Award: $19.01

Gas:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

G01: X += Y COSTS MORE GAS THAN X = X + Y FOR STATE VARIABLES

prof

DBR.sol, 172, b' balances[msg.sender] -= amount;' DBR.sol, 174, b' balances[to] += amount;' DBR.sol, 196, b' balances[from] -= amount;' DBR.sol, 198, b' balances[to] += amount;' DBR.sol, 288, b' dueTokensAccrued[user] += accrued;' DBR.sol, 289, b' totalDueTokensAccrued += accrued;' DBR.sol, 304, b' debts[user] += additionalDebt;' DBR.sol, 316, b' debts[user] -= repaidDebt;' DBR.sol, 332, b' debts[user] += replenishmentCost;' DBR.sol, 360, b' _totalSupply += amount;' DBR.sol, 362, b' balances[to] += amount;' DBR.sol, 374, b' balances[from] -= amount;' DBR.sol, 376, b' _totalSupply -= amount;' Fed.sol, 91, b' supplies[market] += amount;' Fed.sol, 92, b' globalSupply += amount;' Fed.sol, 110, b' supplies[market] -= amount;' Fed.sol, 111, b' globalSupply -= amount;' Market.sol, 395, b' debts[borrower] += amount;' Market.sol, 397, b' totalDebt += amount;' Market.sol, 534, b' debts[user] -= amount;' Market.sol, 535, b' totalDebt -= amount;' Market.sol, 565, b' debts[user] += replenishmentCost;' Market.sol, 568, b' totalDebt += replenishmentCost;' Market.sol, 599, b' debts[user] -= repaidDebt;' Market.sol, 600, b' totalDebt -= repaidDebt;'

G02: ++I/I++ SHOULD BE UNCHECKED{++I}/UNCHECKED{I++} WHEN IT IS NOT POSSIBLE FOR THEM TO OVERFLOW, AS IS THE CASE WHEN USED IN FOR- AND WHILE-LOOPS

problem

The unchecked keyword is new in solidity version 0.8.0, so this only applies to that version or higher, which these instances are. This saves 30-40 gas per loop

prof

BR.sol, 239, b' nonces[owner]++,' DBR.sol, 259, b' nonces[msg.sender]++;' Market.sol, 438, b' nonces[from]++,' Market.sol, 502, b' nonces[from]++,' Market.sol, 521, b' nonces[msg.sender]++;'

G03:ABI.ENCODE() IS LESS EFFICIENT THAN ABI.ENCODEPACKED()

prof

DBR.sol, 232, b' abi.encode(' DBR.sol, 269, b' abi.encode(' Market.sol, 104, b' abi.encode(' Market.sol, 431, b' abi.encode(' Market.sol, 495, b' abi.encode('

G04: Splitting require() statements that use && saves gas

problem

See this issue(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

prof:

DBR.sol, 249, b' require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");' DBR.sol, 350, b' require(minters[msg.sender] == true || msg.sender == operator, "ONLY MINTERS OR OPERATOR");' Market.sol, 75, b' require(_liquidationIncentiveBps > 0 && _liquidationIncentiveBps < 10000, "Invalid liquidation incentive");' Market.sol, 162, b' require(_liquidationFactorBps > 0 && _liquidationFactorBps <= 10000, "Invalid liquidation factor");' Market.sol, 173, b' require(_replenishmentIncentiveBps > 0 && _replenishmentIncentiveBps < 10000, "Invalid replenishment incentive");' Market.sol, 184, b' require(_liquidationIncentiveBps > 0 && _liquidationIncentiveBps + liquidationFeeBps < 10000, "Invalid liquidation incentive");' Market.sol, 195, b' require(_liquidationFeeBps > 0 && _liquidationFeeBps + liquidationIncentiveBps < 10000, "Invalid liquidation fee");' Market.sol, 214, b' require(msg.sender == pauseGuardian || msg.sender == gov, "Only pause guardian or governance can pause");' Market.sol, 448, b' require(recoveredAddress != address(0) && recoveredAddress == from, "INVALID_SIGNER");' Market.sol, 512, b' require(recoveredAddress != address(0) && recoveredAddress == from, "INVALID_SIGNER");'

G05: USING PRIVATE RATHER THAN PUBLIC FOR CONSTANTS, SAVES GAS

problem:

We can save getter function of public constants.

prof:

DBR.sol, 13, b' uint8 public constant decimals = 18;' Fed.sol, 28, b' IDBR public immutable dbr;' Fed.sol, 29, b' IDola public immutable dola;' escrows/INVEscrow.sol, 32, b' IXINV public immutable xINV;' Market.sol, 41, b' address public immutable escrowImplementation;' Market.sol, 42, b' IDolaBorrowingRights public immutable dbr;' Market.sol, 44, b' IERC20 public immutable dola = IERC20(0x865377367054516e17014CcdED1e7d814EDC9ce4);' Market.sol, 45, b' IERC20 public immutable collateral;'

G06: USAGE OF UINTS/INTS SMALLER THAN 32 BYTES (256 BITS) INCURS OVERHEAD

problem

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.

prof

DBR.sol, 13, b' uint8 public constant decimals = 18;' DBR.sol, 63, b' require(newReplenishmentPriceBps_ > 0, "replenishment price must be over 0");' DBR.sol, 110, b' if(totalDueTokensAccrued > _totalSupply) return 0;' DBR.sol, 122, b' uint accrued = (block.timestamp - lastUpdated[user]) * debt / 365 days;' DBR.sol, 123, b' if(dueTokensAccrued[user] + accrued > balances[user]) return 0;' DBR.sol, 135, b' uint accrued = (block.timestamp - lastUpdated[user]) * debt / 365 days;' DBR.sol, 136, b' if(dueTokensAccrued[user] + accrued < balances[user]) return 0;' DBR.sol, 148, b' uint accrued = (block.timestamp - lastUpdated[user]) * debt / 365 days;' DBR.sol, 226, b' address recoveredAddress = ecrecover(' DBR.sol, 245, b' v,' DBR.sol, 249, b' require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");' DBR.sol, 271, b' keccak256(bytes(name)),' DBR.sol, 271, b' keccak256(bytes(name)),' DBR.sol, 287, b' uint accrued = (block.timestamp - lastUpdated[user]) * debt / 365 days;' DBR.sol, 303, b' require(deficitOf(user) == 0, "DBR Deficit");' DBR.sol, 328, b' require(deficit > 0, "No deficit");' DBR.sol, 330, b' uint replenishmentCost = amount * replenishmentPriceBps / 10000;' escrows/SimpleERC20Escrow.sol, 26, b' require(market == address(0), "ALREADY INITIALIZED");' escrows/GovTokenEscrow.sol, 31, b' require(market == address(0), "ALREADY INITIALIZED");' Fed.sol, 123, b' if(supply >= marketValue) return 0;' Fed.sol, 133, b' if(profit > 0) {' Oracle.sol, 79, b' if(fixedPrices[token] > 0) return fixedPrices[token];' Oracle.sol, 80, b' if(feeds[token].feed != IChainlinkFeed(address(0))) {' Oracle.sol, 83, b' require(price > 0, "Invalid feed price");' Oracle.sol, 85, b' uint8 feedDecimals = feeds[token].feed.decimals();' Oracle.sol, 85, b' uint8 feedDecimals = feeds[token].feed.decimals();' Oracle.sol, 85, b' uint8 feedDecimals = feeds[token].feed.decimals();' Oracle.sol, 86, b' uint8 tokenDecimals = feeds[token].tokenDecimals;' Oracle.sol, 86, b' uint8 tokenDecimals = feeds[token].tokenDecimals;' Oracle.sol, 87, b' uint8 decimals = 36 - feedDecimals - tokenDecimals;' Oracle.sol, 87, b' uint8 decimals = 36 - feedDecimals - tokenDecimals;' Oracle.sol, 87, b' uint8 decimals = 36 - feedDecimals - tokenDecimals;' Oracle.sol, 87, b' uint8 decimals = 36 - feedDecimals - tokenDecimals;' Oracle.sol, 87, b' uint8 decimals = 36 - feedDecimals - tokenDecimals;' Oracle.sol, 87, b' uint8 decimals = 36 - feedDecimals - tokenDecimals;' Oracle.sol, 89, b' uint day = block.timestamp / 1 days;' Oracle.sol, 95, b' uint newBorrowingPower = normalizedPrice * collateralFactorBps / 10000;' Oracle.sol, 96, b' uint twoDayLow = todaysLow > yesterdaysLow && yesterdaysLow > 0 ? yesterdaysLow : todaysLow;' Oracle.sol, 97, b' if(twoDayLow > 0 && newBorrowingPower > twoDayLow) {' Oracle.sol, 98, b' uint dampenedPrice = twoDayLow * 10000 / collateralFactorBps;' Oracle.sol, 113, b' if(fixedPrices[token] > 0) return fixedPrices[token];' Oracle.sol, 114, b' if(feeds[token].feed != IChainlinkFeed(address(0))) {' Oracle.sol, 117, b' require(price > 0, "Invalid feed price");' Oracle.sol, 119, b' uint8 feedDecimals = feeds[token].feed.decimals();' Oracle.sol, 119, b' uint8 feedDecimals = feeds[token].feed.decimals();' Oracle.sol, 119, b' uint8 feedDecimals = feeds[token].feed.decimals();' Oracle.sol, 120, b' uint8 tokenDecimals = feeds[token].tokenDecimals;' Oracle.sol, 120, b' uint8 tokenDecimals = feeds[token].tokenDecimals;' Oracle.sol, 121, b' uint8 decimals = 36 - feedDecimals - tokenDecimals;' Oracle.sol, 121, b' uint8 decimals = 36 - feedDecimals - tokenDecimals;' Oracle.sol, 121, b' uint8 decimals = 36 - feedDecimals - tokenDecimals;' Oracle.sol, 121, b' uint8 decimals = 36 - feedDecimals - tokenDecimals;' Oracle.sol, 121, b' uint8 decimals = 36 - feedDecimals - tokenDecimals;' Oracle.sol, 121, b' uint8 decimals = 36 - feedDecimals - tokenDecimals;' Oracle.sol, 124, b' uint day = block.timestamp / 1 days;' Oracle.sol, 126, b' if(todaysLow == 0 || normalizedPrice < todaysLow) {' Oracle.sol, 134, b' uint newBorrowingPower = normalizedPrice * collateralFactorBps / 10000;' Oracle.sol, 135, b' uint twoDayLow = todaysLow > yesterdaysLow && yesterdaysLow > 0 ? yesterdaysLow : todaysLow;' Oracle.sol, 136, b' if(twoDayLow > 0 && newBorrowingPower > twoDayLow) {' Oracle.sol, 137, b' uint dampenedPrice = twoDayLow * 10000 / collateralFactorBps;' escrows/INVEscrow.sol, 45, b' require(market == address(0), "ALREADY INITIALIZED");' escrows/INVEscrow.sol, 72, b' uint invBalanceInXInv = xINV.balanceOf(address(this)) * xINV.exchangeRateStored() / 1 ether;' escrows/INVEscrow.sol, 81, b' if(invBalance > 0) {' Market.sol, 74, b' require(_collateralFactorBps < 10000, "Invalid collateral factor");' Market.sol, 75, b' require(_liquidationIncentiveBps > 0 && _liquidationIncentiveBps < 10000, "Invalid liquidation incentive");' Market.sol, 75, b' require(_liquidationIncentiveBps > 0 && _liquidationIncentiveBps < 10000, "Invalid liquidation incentive");' Market.sol, 76, b' require(_replenishmentIncentiveBps < 10000, "Replenishment incentive must be less than 100%");' Market.sol, 106, b' keccak256(bytes("DBR MARKET")),' Market.sol, 150, b' require(_collateralFactorBps < 10000, "Invalid collateral factor");' Market.sol, 162, b' require(_liquidationFactorBps > 0 && _liquidationFactorBps <= 10000, "Invalid liquidation factor");' Market.sol, 162, b' require(_liquidationFactorBps > 0 && _liquidationFactorBps <= 10000, "Invalid liquidation factor");' Market.sol, 173, b' require(_replenishmentIncentiveBps > 0 && _replenishmentIncentiveBps < 10000, "Invalid replenishment incentive");' Market.sol, 173, b' require(_replenishmentIncentiveBps > 0 && _replenishmentIncentiveBps < 10000, "Invalid replenishment incentive");' Market.sol, 184, b' require(_liquidationIncentiveBps > 0 && _liquidationIncentiveBps + liquidationFeeBps < 10000, "Invalid liquidation incentive");' Market.sol, 184, b' require(_liquidationIncentiveBps > 0 && _liquidationIncentiveBps + liquidationFeeBps < 10000, "Invalid liquidation incentive");' Market.sol, 195, b' require(_liquidationFeeBps > 0 && _liquidationFeeBps + liquidationIncentiveBps < 10000, "Invalid liquidation fee");' Market.sol, 195, b' require(_liquidationFeeBps > 0 && _liquidationFeeBps + liquidationIncentiveBps < 10000, "Invalid liquidation fee");' Market.sol, 236, b' require(instance != IEscrow(address(0)), "ERC1167: create2 failed");' Market.sol, 246, b' if(escrows[user] != IEscrow(address(0))) return escrows[user];' Market.sol, 315, b' return collateralBalance * oracle.viewPrice(address(collateral), collateralFactorBps) / 1 ether;' Market.sol, 326, b' return collateralBalance * oracle.getPrice(address(collateral), collateralFactorBps) / 1 ether;' Market.sol, 336, b' return collateralValue * collateralFactorBps / 10000;' Market.sol, 346, b' return collateralValue * collateralFactorBps / 10000;' Market.sol, 356, b' if(collateralBalance == 0) return 0;' Market.sol, 356, b' if(collateralBalance == 0) return 0;' Market.sol, 358, b' if(debt == 0) return collateralBalance;' Market.sol, 359, b' if(collateralFactorBps == 0) return 0;' Market.sol, 359, b' if(collateralFactorBps == 0) return 0;' Market.sol, 360, b' uint minimumCollateral = debt * 1 ether / oracle.getPrice(address(collateral), collateralFactorBps) * 10000 / collateralFactorBps;' Market.sol, 360, b' uint minimumCollateral = debt * 1 ether / oracle.getPrice(address(collateral), collateralFactorBps) * 10000 / collateralFactorBps;' Market.sol, 361, b' if(collateralBalance <= minimumCollateral) return 0;' Market.sol, 373, b' if(collateralBalance == 0) return 0;' Market.sol, 373, b' if(collateralBalance == 0) return 0;' Market.sol, 375, b' if(debt == 0) return collateralBalance;' Market.sol, 376, b' if(collateralFactorBps == 0) return 0;' Market.sol, 376, b' if(collateralFactorBps == 0) return 0;' Market.sol, 377, b' uint minimumCollateral = debt * 1 ether / oracle.viewPrice(address(collateral), collateralFactorBps) * 10000 / collateralFactorBps;' Market.sol, 377, b' uint minimumCollateral = debt * 1 ether / oracle.viewPrice(address(collateral), collateralFactorBps) * 10000 / collateralFactorBps;' Market.sol, 378, b' if(collateralBalance <= minimumCollateral) return 0;' Market.sol, 391, b' if(borrowController != IBorrowController(address(0))) {' Market.sol, 425, b' address recoveredAddress = ecrecover(' Market.sol, 444, b' v,' Market.sol, 448, b' require(recoveredAddress != address(0) && recoveredAddress == from, "INVALID_SIGNER");' Market.sol, 489, b' address recoveredAddress = ecrecover(' Market.sol, 508, b' v,' Market.sol, 512, b' require(recoveredAddress != address(0) && recoveredAddress == from, "INVALID_SIGNER");' Market.sol, 561, b' require(deficit > 0, "No DBR deficit");' Market.sol, 563, b' uint replenishmentCost = amount * dbr.replenishmentPriceBps() / 10000;' Market.sol, 564, b' uint replenisherReward = replenishmentCost * replenishmentIncentiveBps / 10000;' Market.sol, 580, b' if (debt == 0) return 0;' Market.sol, 580, b' if (debt == 0) return 0;' Market.sol, 582, b' if(credit >= debt) return 0;' Market.sol, 583, b' return debt * liquidationFactorBps / 10000;' Market.sol, 592, b' require(repaidDebt > 0, "Must repay positive debt");' Market.sol, 595, b' require(repaidDebt <= debt * liquidationFactorBps / 10000, "Exceeded liquidation factor");' Market.sol, 597, b' uint liquidatorReward = repaidDebt * 1 ether / price;' Market.sol, 605, b' if(liquidationFeeBps > 0) {' Market.sol, 606, b' uint liquidationFee = repaidDebt * 1 ether / price * liquidationFeeBps / 10000;' Market.sol, 606, b' uint liquidationFee = repaidDebt * 1 ether / price * liquidationFeeBps / 10000;'

#0 - c4-judge

2022-11-05T23:39:51Z

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