Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gas Optimizations #74

Open
code423n4 opened this issue May 1, 2022 · 1 comment
Open

Gas Optimizations #74

code423n4 opened this issue May 1, 2022 · 1 comment
Labels
bug Something isn't working G (Gas Optimization)

Comments

@code423n4
Copy link
Contributor

Gas Optimizations

1. State variables should be cached in stack variables rather than re-reading them from storage

The instances below point to the second or later access of a state variable within a function. Caching will replace each Gwarmaccess (100 gas) with a much cheaper stack read.
Less obvious fixes/optimizations include having local storage variables of mappings within state variable mappings or mappings within state variable structs, having local storage variables of structs within mappings, or having local caches of state variable contracts/addresses.

File: contracts/NFTPair.sol   #1

178           require(address(collateral) != address(0), "NFTPair: bad pair");

collateral
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L178

File: contracts/NFTPair.sol   #2

297                   bentoBox.balanceOf(asset, address(this)) >= (totalShare - openFeeShare + protocolFeeShare + feesEarnedShare),

asset
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L297

File: contracts/NFTPair.sol   #3

301               bentoBox.transfer(asset, lender, address(this), totalShare - openFeeShare + protocolFeeShare);

asset
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L301

File: contracts/NFTPair.sol   #4

305           bentoBox.transfer(asset, address(this), loan.borrower, borrowerShare);

asset
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L305

File: contracts/NFTPair.sol   #5

524           uint256 feeShare = bentoBox.toShare(asset, fee, false);

asset
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L524

File: contracts/NFTPair.sol   #6

528               require(bentoBox.balanceOf(asset, address(this)) >= (totalShare + feesEarnedShare), "NFTPair: skim too much");

asset
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L528

File: contracts/NFTPair.sol   #7

532               bentoBox.transfer(asset, msg.sender, address(this), feeShare);

asset
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L532

File: contracts/NFTPair.sol   #8

539           bentoBox.transfer(asset, from, loan.lender, totalShare - feeShare);

asset
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L539

File: contracts/NFTPairWithOracle.sol   #9

195           require(address(collateral) != address(0), "NFTPair: bad pair");

collateral
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L195

File: contracts/NFTPairWithOracle.sol   #10

332                   bentoBox.balanceOf(asset, address(this)) >= (totalShare - openFeeShare + protocolFeeShare + feesEarnedShare),

asset
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L332

File: contracts/NFTPairWithOracle.sol   #11

336               bentoBox.transfer(asset, lender, address(this), totalShare - openFeeShare + protocolFeeShare);

asset
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L336

File: contracts/NFTPairWithOracle.sol   #12

340           bentoBox.transfer(asset, address(this), loan.borrower, borrowerShare);

asset
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L340

File: contracts/NFTPairWithOracle.sol   #13

557           uint256 feeShare = bentoBox.toShare(asset, fee, false);

asset
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L557

File: contracts/NFTPairWithOracle.sol   #14

561               require(bentoBox.balanceOf(asset, address(this)) >= (totalShare + feesEarnedShare), "NFTPair: skim too much");

asset
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L561

File: contracts/NFTPairWithOracle.sol   #15

565               bentoBox.transfer(asset, msg.sender, address(this), feeShare);

asset
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L565

File: contracts/NFTPairWithOracle.sol   #16

572           bentoBox.transfer(asset, from, loan.lender, totalShare - feeShare);

asset
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L572

File: contracts/NFTPairWithOracle.sol   #17

278                   TokenLoanParams memory loanParams = tokenLoanParams[tokenId];

tokenLoanParams
https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L278

2. <x> += <y> costs more gas than <x> = <x> + <y> for state variables

File: contracts/NFTPair.sol   #1

307           feesEarnedShare += protocolFeeShare;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L307

File: contracts/NFTPair.sol   #2

536           feesEarnedShare += feeShare;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L536

File: contracts/NFTPairWithOracle.sol   #3

342           feesEarnedShare += protocolFeeShare;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L342

File: contracts/NFTPairWithOracle.sol   #4

569           feesEarnedShare += feeShare;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L569

3. <array>.length should not be looked up in every loop of a for-loop

The overheads outlined below are PER LOOP, excluding the first loop

  • storage arrays incur a Gwarmaccess (100 gas)
  • memory arrays use MLOAD (3 gas)
  • calldata arrays use CALLDATALOAD (3 gas)

Caching the length changes each of these to a DUP<N> (3 gas), and gets rid of the extra DUP<N> needed to store the stack offset

File: contracts/NFTPair.sol   #1

641           for (uint256 i = 0; i < actions.length; i++) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L641

File: contracts/NFTPairWithOracle.sol   #2

674           for (uint256 i = 0; i < actions.length; i++) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L674

4. require()/revert() strings longer than 32 bytes cost extra gas

File: contracts/NFTPair.sol   #1

366               require(ILendingClub(lender).willLend(tokenId, params), "NFTPair: LendingClub does not like you");

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L366

File: contracts/NFTPairWithOracle.sol   #2

398               require(ILendingClub(lender).willLend(tokenId, params), "NFTPair: LendingClub does not like you");

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L398

5. Use a more recent version of solidity

Use a solidity version of at least 0.8.0 to get overflow protection without SafeMath
Use a solidity version of at least 0.8.2 to get compiler automatic inlining
Use a solidity version of at least 0.8.3 to get better struct packing and cheaper multiple storage reads
Use a solidity version of at least 0.8.4 to get custom errors, which are cheaper at deployment than revert()/require() strings
Use a solidity version of at least 0.8.10 to have external calls skip contract existence checks if the external call has a return value

File: contracts/NFTPair.sol   #1

20   pragma solidity 0.6.12;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L20

File: contracts/NFTPairWithOracle.sol   #2

20   pragma solidity 0.6.12;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L20

6. It costs more gas to initialize variables to zero than to let the default of zero be applied

File: contracts/NFTPair.sol   #1

641           for (uint256 i = 0; i < actions.length; i++) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L641

File: contracts/NFTPairWithOracle.sol   #2

674           for (uint256 i = 0; i < actions.length; i++) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L674

7. internal functions only called once can be inlined to save gas

Not inlining costs 20 to 40 gas because of two extra JUMP instructions and additional stack operations needed for function calls.

File: contracts/NFTPair.sol   #1

578       function _bentoDeposit(
579           bytes memory data,
580           uint256 value,
581           uint256 value1,
582           uint256 value2
583       ) internal returns (uint256, uint256) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L578-L583

File: contracts/NFTPair.sol   #2

591       function _bentoWithdraw(
592           bytes memory data,
593           uint256 value1,
594           uint256 value2
595       ) internal returns (uint256, uint256) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L591-L595

File: contracts/NFTPair.sol   #3

603       function _call(
604           uint256 value,
605           bytes memory data,
606           uint256 value1,
607           uint256 value2
608       ) internal returns (bytes memory, uint8) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L603-L608

File: contracts/NFTPairWithOracle.sol   #4

611       function _bentoDeposit(
612           bytes memory data,
613           uint256 value,
614           uint256 value1,
615           uint256 value2
616       ) internal returns (uint256, uint256) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L611-L616

File: contracts/NFTPairWithOracle.sol   #5

624       function _bentoWithdraw(
625           bytes memory data,
626           uint256 value1,
627           uint256 value2
628       ) internal returns (uint256, uint256) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L624-L628

File: contracts/NFTPairWithOracle.sol   #6

636       function _call(
637           uint256 value,
638           bytes memory data,
639           uint256 value1,
640           uint256 value2
641       ) internal returns (bytes memory, uint8) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L636-L641

8. Using calldata instead of memory for read-only arguments in external functions saves gas

When a function with a memory array is called externally, the abi.decode() step has to use a for-loop to copy each index of the calldata to the memory index. Each iteration of this for-loop costs at least 60 gas (i.e. 60 * <mem_array>.length). Using calldata directly, obliviates the need for such a loop in the contract code and runtime execution. Structs have the same overhead as an array of length one

File: contracts/NFTPair.sol   #1

39       function willLend(uint256 tokenId, TokenLoanParams memory params) external view returns (bool);

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L39

File: contracts/NFTPairWithOracle.sol   #2

49       function willLend(uint256 tokenId, TokenLoanParams memory params) external view returns (bool);

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L49

9. ++i costs less gas than ++i, especially when it's used in for-loops (--i/i-- too)

File: contracts/NFTPair.sol   #1

494           for (uint256 k = 2; k <= COMPOUND_INTEREST_TERMS; k++) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L494

File: contracts/NFTPair.sol   #2

641           for (uint256 i = 0; i < actions.length; i++) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L641

File: contracts/NFTPairWithOracle.sol   #3

527           for (uint256 k = 2; k <= COMPOUND_INTEREST_TERMS; k++) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L527

File: contracts/NFTPairWithOracle.sol   #4

674           for (uint256 i = 0; i < actions.length; i++) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L674

10. Splitting require() statements that use && saves gas

See this issue for an example

File: contracts/NFTPair.sol   #1

188               require(
189                   params.duration >= cur.duration && params.valuation <= cur.valuation && params.annualInterestBPS <= cur.annualInterestBPS,
190                   "NFTPair: worse params"
191               );

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L188-L191

File: contracts/NFTPair.sol   #2

283           require(
284               params.valuation == accepted.valuation &&
285                   params.duration <= accepted.duration &&
286                   params.annualInterestBPS >= accepted.annualInterestBPS,
287               "NFTPair: bad params"
288           );

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L283-L288

File: contracts/NFTPair.sol   #3

622           require(callee != address(bentoBox) && callee != address(collateral) && callee != address(this), "NFTPair: can't call");

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L622

File: contracts/NFTPairWithOracle.sol   #4

205               require(
206                   params.duration >= cur.duration &&
207                       params.valuation <= cur.valuation &&
208                       params.annualInterestBPS <= cur.annualInterestBPS &&
209                       params.ltvBPS <= cur.ltvBPS,
210                   "NFTPair: worse params"
211               );

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L205-L211

File: contracts/NFTPairWithOracle.sol   #5

312           require(
313               params.valuation == accepted.valuation &&
314                   params.duration <= accepted.duration &&
315                   params.annualInterestBPS >= accepted.annualInterestBPS &&
316                   params.ltvBPS >= accepted.ltvBPS,
317               "NFTPair: bad params"
318           );

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L312-L318

File: contracts/NFTPairWithOracle.sol   #6

655           require(callee != address(bentoBox) && callee != address(collateral) && callee != address(this), "NFTPair: can't call");

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L655

11. 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
Use a larger size then downcast where needed

File: contracts/NFTPair.sol   #1

32       uint128 valuation; // How much will you get? OK to owe until expiration.

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L32

File: contracts/NFTPair.sol   #2

33       uint64 duration; // Length of loan in seconds

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L33

File: contracts/NFTPair.sol   #3

34       uint16 annualInterestBPS; // Variable cost of taking out the loan

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L34

File: contracts/NFTPair.sol   #4

65       event LogRequestLoan(address indexed borrower, uint256 indexed tokenId, uint128 valuation, uint64 duration, uint16 annualInterestBPS);

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L65

File: contracts/NFTPair.sol   #5

65       event LogRequestLoan(address indexed borrower, uint256 indexed tokenId, uint128 valuation, uint64 duration, uint16 annualInterestBPS);

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L65

File: contracts/NFTPair.sol   #6

65       event LogRequestLoan(address indexed borrower, uint256 indexed tokenId, uint128 valuation, uint64 duration, uint16 annualInterestBPS);

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L65

File: contracts/NFTPair.sol   #7

66       event LogUpdateLoanParams(uint256 indexed tokenId, uint128 valuation, uint64 duration, uint16 annualInterestBPS);

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L66

File: contracts/NFTPair.sol   #8

66       event LogUpdateLoanParams(uint256 indexed tokenId, uint128 valuation, uint64 duration, uint16 annualInterestBPS);

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L66

File: contracts/NFTPair.sol   #9

66       event LogUpdateLoanParams(uint256 indexed tokenId, uint128 valuation, uint64 duration, uint16 annualInterestBPS);

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L66

File: contracts/NFTPair.sol   #10

96       uint8 private constant LOAN_INITIAL = 0;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L96

File: contracts/NFTPair.sol   #11

97       uint8 private constant LOAN_REQUESTED = 1;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L97

File: contracts/NFTPair.sol   #12

98       uint8 private constant LOAN_OUTSTANDING = 2;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L98

File: contracts/NFTPair.sol   #13

102           uint64 startTime;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L102

File: contracts/NFTPair.sol   #14

103           uint8 status;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L103

File: contracts/NFTPair.sol   #15

162       uint8 private constant COMPOUND_INTEREST_TERMS = 6;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L162

File: contracts/NFTPair.sol   #16

361           uint8 v,

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L361

File: contracts/NFTPair.sol   #17

401           uint8 v,

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L401

File: contracts/NFTPair.sol   #18

443           uint64 t,

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L443

File: contracts/NFTPair.sol   #19

444           uint16 aprBPS

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L444

File: contracts/NFTPair.sol   #20

515           uint128 principal = loanParams.valuation;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L515

File: contracts/NFTPair.sol   #21

545       uint8 internal constant ACTION_REPAY = 2;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L545

File: contracts/NFTPair.sol   #22

546       uint8 internal constant ACTION_REMOVE_COLLATERAL = 4;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L546

File: contracts/NFTPair.sol   #23

548       uint8 internal constant ACTION_REQUEST_LOAN = 12;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L548

File: contracts/NFTPair.sol   #24

549       uint8 internal constant ACTION_LEND = 13;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L549

File: contracts/NFTPair.sol   #25

552       uint8 internal constant ACTION_BENTO_DEPOSIT = 20;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L552

File: contracts/NFTPair.sol   #26

553       uint8 internal constant ACTION_BENTO_WITHDRAW = 21;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L553

File: contracts/NFTPair.sol   #27

554       uint8 internal constant ACTION_BENTO_TRANSFER = 22;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L554

File: contracts/NFTPair.sol   #28

555       uint8 internal constant ACTION_BENTO_TRANSFER_MULTIPLE = 23;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L555

File: contracts/NFTPair.sol   #29

556       uint8 internal constant ACTION_BENTO_SETAPPROVAL = 24;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L556

File: contracts/NFTPair.sol   #30

559       uint8 internal constant ACTION_CALL = 30;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L559

File: contracts/NFTPair.sol   #31

562       uint8 internal constant ACTION_REQUEST_AND_BORROW = 40;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L562

File: contracts/NFTPair.sol   #32

563       uint8 internal constant ACTION_TAKE_COLLATERAL_AND_LEND = 41;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L563

File: contracts/NFTPair.sol   #33

608       ) internal returns (bytes memory, uint8) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L608

File: contracts/NFTPair.sol   #34

609           (address callee, bytes memory callData, bool useValue1, bool useValue2, uint8 returnValues) = abi.decode(

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L609

File: contracts/NFTPair.sol   #35

642               uint8 action = actions[i];

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L642

File: contracts/NFTPair.sol   #36

659                   (address user, address _masterContract, bool approved, uint8 v, bytes32 r, bytes32 s) = abi.decode(

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L659

File: contracts/NFTPair.sol   #37

675                   (bytes memory returnData, uint8 returnValues) = _call(values[i], datas[i], value1, value2);

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L675

File: contracts/NFTPair.sol   #38

691                       uint8 v,

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L691

File: contracts/NFTPair.sol   #39

703                       uint8 v,

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L703

File: contracts/NFTPairWithOracle.sol   #40

33       uint128 valuation; // How much will you get? OK to owe until expiration.

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L33

File: contracts/NFTPairWithOracle.sol   #41

34       uint64 duration; // Length of loan in seconds

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L34

File: contracts/NFTPairWithOracle.sol   #42

35       uint16 annualInterestBPS; // Variable cost of taking out the loan

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L35

File: contracts/NFTPairWithOracle.sol   #43

36       uint16 ltvBPS; // Required to avoid liquidation

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L36

File: contracts/NFTPairWithOracle.sol   #44

42       uint8 v;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L42

File: contracts/NFTPairWithOracle.sol   #45

78           uint128 valuation,

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L78

File: contracts/NFTPairWithOracle.sol   #46

79           uint64 duration,

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L79

File: contracts/NFTPairWithOracle.sol   #47

80           uint16 annualInterestBPS,

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L80

File: contracts/NFTPairWithOracle.sol   #48

81           uint16 ltvBPS

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L81

File: contracts/NFTPairWithOracle.sol   #49

83       event LogUpdateLoanParams(uint256 indexed tokenId, uint128 valuation, uint64 duration, uint16 annualInterestBPS, uint16 ltvBPS);

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L83

File: contracts/NFTPairWithOracle.sol   #50

83       event LogUpdateLoanParams(uint256 indexed tokenId, uint128 valuation, uint64 duration, uint16 annualInterestBPS, uint16 ltvBPS);

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L83

File: contracts/NFTPairWithOracle.sol   #51

83       event LogUpdateLoanParams(uint256 indexed tokenId, uint128 valuation, uint64 duration, uint16 annualInterestBPS, uint16 ltvBPS);

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L83

File: contracts/NFTPairWithOracle.sol   #52

83       event LogUpdateLoanParams(uint256 indexed tokenId, uint128 valuation, uint64 duration, uint16 annualInterestBPS, uint16 ltvBPS);

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L83

File: contracts/NFTPairWithOracle.sol   #53

113       uint8 private constant LOAN_INITIAL = 0;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L113

File: contracts/NFTPairWithOracle.sol   #54

114       uint8 private constant LOAN_REQUESTED = 1;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L114

File: contracts/NFTPairWithOracle.sol   #55

115       uint8 private constant LOAN_OUTSTANDING = 2;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L115

File: contracts/NFTPairWithOracle.sol   #56

119           uint64 startTime;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L119

File: contracts/NFTPairWithOracle.sol   #57

120           uint8 status;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L120

File: contracts/NFTPairWithOracle.sol   #58

179       uint8 private constant COMPOUND_INTEREST_TERMS = 6;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L179

File: contracts/NFTPairWithOracle.sol   #59

476           uint64 t,

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L476

File: contracts/NFTPairWithOracle.sol   #60

477           uint16 aprBPS

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L477

File: contracts/NFTPairWithOracle.sol   #61

548           uint128 principal = loanParams.valuation;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L548

File: contracts/NFTPairWithOracle.sol   #62

578       uint8 internal constant ACTION_REPAY = 2;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L578

File: contracts/NFTPairWithOracle.sol   #63

579       uint8 internal constant ACTION_REMOVE_COLLATERAL = 4;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L579

File: contracts/NFTPairWithOracle.sol   #64

581       uint8 internal constant ACTION_REQUEST_LOAN = 12;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L581

File: contracts/NFTPairWithOracle.sol   #65

582       uint8 internal constant ACTION_LEND = 13;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L582

File: contracts/NFTPairWithOracle.sol   #66

585       uint8 internal constant ACTION_BENTO_DEPOSIT = 20;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L585

File: contracts/NFTPairWithOracle.sol   #67

586       uint8 internal constant ACTION_BENTO_WITHDRAW = 21;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L586

File: contracts/NFTPairWithOracle.sol   #68

587       uint8 internal constant ACTION_BENTO_TRANSFER = 22;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L587

File: contracts/NFTPairWithOracle.sol   #69

588       uint8 internal constant ACTION_BENTO_TRANSFER_MULTIPLE = 23;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L588

File: contracts/NFTPairWithOracle.sol   #70

589       uint8 internal constant ACTION_BENTO_SETAPPROVAL = 24;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L589

File: contracts/NFTPairWithOracle.sol   #71

592       uint8 internal constant ACTION_CALL = 30;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L592

File: contracts/NFTPairWithOracle.sol   #72

595       uint8 internal constant ACTION_REQUEST_AND_BORROW = 40;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L595

File: contracts/NFTPairWithOracle.sol   #73

596       uint8 internal constant ACTION_TAKE_COLLATERAL_AND_LEND = 41;

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L596

File: contracts/NFTPairWithOracle.sol   #74

641       ) internal returns (bytes memory, uint8) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L641

File: contracts/NFTPairWithOracle.sol   #75

642           (address callee, bytes memory callData, bool useValue1, bool useValue2, uint8 returnValues) = abi.decode(

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L642

File: contracts/NFTPairWithOracle.sol   #76

675               uint8 action = actions[i];

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L675

File: contracts/NFTPairWithOracle.sol   #77

692                   (address user, address _masterContract, bool approved, uint8 v, bytes32 r, bytes32 s) = abi.decode(

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L692

File: contracts/NFTPairWithOracle.sol   #78

708                   (bytes memory returnData, uint8 returnValues) = _call(values[i], datas[i], value1, value2);

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L708

12. Duplicated require()/revert() checks should be refactored to a modifier or function

Saves deployment costs

File: contracts/NFTPair.sol   #1

251               require(msg.sender == loan.borrower, "NFTPair: not the borrower");

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L251

File: contracts/NFTPair.sol   #2

405           require(block.timestamp <= deadline, "NFTPair: signature expired");

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L405

File: contracts/NFTPairWithOracle.sol   #3

271               require(msg.sender == loan.borrower, "NFTPair: not the borrower");

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L271

File: contracts/NFTPairWithOracle.sol   #4

436           require(block.timestamp <= signature.deadline, "NFTPair: signature expired");

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L436

13. Functions guaranteed to revert when called by normal users can be marked payable

If a function modifier such as onlyOwner is used, the function will revert if a normal user tries to pay the function. Marking the function as payable will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided. The extra opcodes avoided are
CALLVALUE(2),DUP1(3),ISZERO(3),PUSH2(3),JUMPI(10),PUSH1(3),DUP1(3),REVERT(0),JUMPDEST(1),POP(2), which costs an average of about 21 gas per call to the function, in addition to the extra deployment cost

File: contracts/NFTPair.sol   #1

728       function setFeeTo(address newFeeTo) public onlyOwner {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L728

File: contracts/NFTPairWithOracle.sol   #2

750       function setFeeTo(address newFeeTo) public onlyOwner {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L750

14. > uint128(-1) is cheaper than >= 2**128

File: contracts/NFTPair.sol   #1

500          if (interest >= 2**128) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPair.sol#L500

File: contracts/NFTPairWithOracle.sol   #2

533          if (interest >= 2**128) {

https://github.com/code-423n4/2022-04-abranft/blob/5cd4edc3298c05748e952f8a8c93e42f930a78c2/contracts/NFTPairWithOracle.sol#L533

@code423n4 code423n4 added bug Something isn't working G (Gas Optimization) labels May 1, 2022
code423n4 added a commit that referenced this issue May 1, 2022
@cryptolyndon
Copy link
Collaborator

cryptolyndon commented May 14, 2022

1 is valid.

11 probably contains a few opportunities, but suggesting that structs, one of which currently fits in 256 bits, use all 256-bit values casts suspicion over the rest of the entire report. Did that get in by accident?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working G (Gas Optimization)
Projects
None yet
Development

No branches or pull requests

2 participants