If not cached, the solidity compiler will always read the length of the array during each iteration. That is, if it is a storage array, this is an extra sload operation (100 additional extra gas for each iteration except for the first) and if it is a memory array, this is an extra mload operation (3 additional gas for each iteration except for the first).
File: Beedle.sol
4: import {Ownable} from "./utils/Ownable.sol";
4: import {Ownable} from "./utils/Ownable.sol";
5: import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
5: import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
5: import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
5: import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
5: import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
6: import {ERC20Permit} from "openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
6: import {ERC20Permit} from "openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
6: import {ERC20Permit} from "openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
6: import {ERC20Permit} from "openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
6: import {ERC20Permit} from "openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
6: import {ERC20Permit} from "openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
6: import {ERC20Permit} from "openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
7: import {ERC20Votes} from "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol";
7: import {ERC20Votes} from "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol";
7: import {ERC20Votes} from "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol";
7: import {ERC20Votes} from "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol";
7: import {ERC20Votes} from "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol";
7: import {ERC20Votes} from "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol";
12: _mint(msg.sender, 1_000_000_000 * 1e18);
File: Lender.sol
4: import "./utils/Errors.sol";
4: import "./utils/Errors.sol";
5: import "./utils/Structs.sol";
5: import "./utils/Structs.sol";
7: import {IERC20} from "./interfaces/IERC20.sol";
7: import {IERC20} from "./interfaces/IERC20.sol";
8: import {Ownable} from "./utils/Ownable.sol";
8: import {Ownable} from "./utils/Ownable.sol";
120: debt = loan.debt + interest + fees;
120: debt = loan.debt + interest + fees;
155: p.poolBalance - currentBalance
161: currentBalance - p.poolBalance
185: _updatePoolBalance(poolId, pools[poolId].poolBalance + amount);
201: _updatePoolBalance(poolId, pools[poolId].poolBalance - amount);
233: for (uint256 i = 0; i < borrows.length; i++) {
233: for (uint256 i = 0; i < borrows.length; i++) {
246: uint256 loanRatio = (debt * 10 ** 18) / collateral;
246: uint256 loanRatio = (debt * 10 ** 18) / collateral;
246: uint256 loanRatio = (debt * 10 ** 18) / collateral;
246: uint256 loanRatio = (debt * 10 ** 18) / collateral;
262: _updatePoolBalance(poolId, pools[poolId].poolBalance - debt);
263: pools[poolId].outstandingLoans += debt;
265: uint256 fees = (debt * borrowerFee) / 10000;
265: uint256 fees = (debt * borrowerFee) / 10000;
269: IERC20(loan.loanToken).transfer(msg.sender, debt - fees);
280: loans.length - 1,
293: for (uint256 i = 0; i < loanIds.length; i++) {
293: for (uint256 i = 0; i < loanIds.length; i++) {
312: pools[poolId].poolBalance + loan.debt + lenderInterest
312: pools[poolId].poolBalance + loan.debt + lenderInterest
314: pools[poolId].outstandingLoans -= loan.debt;
320: loan.debt + lenderInterest
359: for (uint256 i = 0; i < loanIds.length; i++) {
359: for (uint256 i = 0; i < loanIds.length; i++) {
381: uint256 totalDebt = loan.debt + lenderInterest + protocolInterest;
381: uint256 totalDebt = loan.debt + lenderInterest + protocolInterest;
384: uint256 loanRatio = (totalDebt * 10 ** 18) / loan.collateral;
384: uint256 loanRatio = (totalDebt * 10 ** 18) / loan.collateral;
384: uint256 loanRatio = (totalDebt * 10 ** 18) / loan.collateral;
384: uint256 loanRatio = (totalDebt * 10 ** 18) / loan.collateral;
387: _updatePoolBalance(poolId, pool.poolBalance - totalDebt);
388: pools[poolId].outstandingLoans += totalDebt;
398: pools[oldPoolId].poolBalance + loan.debt + lenderInterest
398: pools[oldPoolId].poolBalance + loan.debt + lenderInterest
400: pools[oldPoolId].outstandingLoans -= loan.debt;
409: loan.debt + lenderInterest + protocolInterest,
409: loan.debt + lenderInterest + protocolInterest,
438: for (uint256 i = 0; i < loanIds.length; i++) {
438: for (uint256 i = 0; i < loanIds.length; i++) {
471: if (block.timestamp > loan.auctionStartTimestamp + loan.auctionLength)
474: uint256 timeElapsed = block.timestamp - loan.auctionStartTimestamp;
475: uint256 currentAuctionRate = (MAX_INTEREST_RATE * timeElapsed) /
475: uint256 currentAuctionRate = (MAX_INTEREST_RATE * timeElapsed) /
485: uint256 totalDebt = loan.debt + lenderInterest + protocolInterest;
485: uint256 totalDebt = loan.debt + lenderInterest + protocolInterest;
489: _updatePoolBalance(poolId, pools[poolId].poolBalance - totalDebt);
490: pools[poolId].outstandingLoans += totalDebt;
500: pools[oldPoolId].poolBalance + loan.debt + lenderInterest
500: pools[oldPoolId].poolBalance + loan.debt + lenderInterest
502: pools[oldPoolId].outstandingLoans -= loan.debt;
511: loan.debt + lenderInterest + protocolInterest,
511: loan.debt + lenderInterest + protocolInterest,
549: for (uint256 i = 0; i < loanIds.length; i++) {
549: for (uint256 i = 0; i < loanIds.length; i++) {
558: loan.auctionStartTimestamp + loan.auctionLength
561: uint256 govFee = (borrowerFee * loan.collateral) / 10000;
561: uint256 govFee = (borrowerFee * loan.collateral) / 10000;
567: loan.collateral - govFee
575: pools[poolId].outstandingLoans -= loan.debt;
592: for (uint256 i = 0; i < refinances.length; i++) {
592: for (uint256 i = 0; i < refinances.length; i++) {
618: uint256 loanRatio = (debt * 10 ** 18) / collateral;
618: uint256 loanRatio = (debt * 10 ** 18) / collateral;
618: uint256 loanRatio = (debt * 10 ** 18) / collateral;
618: uint256 loanRatio = (debt * 10 ** 18) / collateral;
626: uint256 debtToPay = loan.debt + lenderInterest + protocolInterest;
626: uint256 debtToPay = loan.debt + lenderInterest + protocolInterest;
631: pools[oldPoolId].poolBalance + loan.debt + lenderInterest
631: pools[oldPoolId].poolBalance + loan.debt + lenderInterest
633: pools[oldPoolId].outstandingLoans -= loan.debt;
636: _updatePoolBalance(poolId, pools[poolId].poolBalance - debt);
637: pools[poolId].outstandingLoans += debt;
645: debtToPay - debt
650: uint256 fee = (borrowerFee * (debt - debtToPay)) / 10000;
650: uint256 fee = (borrowerFee * (debt - debtToPay)) / 10000;
650: uint256 fee = (borrowerFee * (debt - debtToPay)) / 10000;
653: IERC20(loan.loanToken).transfer(msg.sender, debt - debtToPay - fee);
653: IERC20(loan.loanToken).transfer(msg.sender, debt - debtToPay - fee);
666: collateral - loan.collateral
672: loan.collateral - collateral
698: pools[poolId].poolBalance -= debt;
723: uint256 timeElapsed = block.timestamp - l.startTimestamp;
724: interest = (l.interestRate * l.debt * timeElapsed) / 10000 / 365 days;
724: interest = (l.interestRate * l.debt * timeElapsed) / 10000 / 365 days;
724: interest = (l.interestRate * l.debt * timeElapsed) / 10000 / 365 days;
724: interest = (l.interestRate * l.debt * timeElapsed) / 10000 / 365 days;
725: fees = (lenderFee * interest) / 10000;
725: fees = (lenderFee * interest) / 10000;
726: interest -= fees;
If needed, the values can be read from the verified contract source code, or if there are multiple values there can be a single getter function that returns a tuple of the values of all currently-public constants. Saves 3406-3606 gas in deployment gas due to the compiler not having to create non-payable getter functions for deployment calldata, not having to store the bytes of the value outside of where it's used, and not adding another entry to the method ID table