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 #6

Open
code423n4 opened this issue Apr 5, 2022 · 2 comments
Open

Gas Optimizations #6

code423n4 opened this issue Apr 5, 2022 · 2 comments
Labels
bug Something isn't working G (Gas Optimization) resolved Finding has been patched by sponsor (sponsor pls link to PR containing fix) sponsor confirmed Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")

Comments

@code423n4
Copy link
Contributor

-- 1
All functions that receive uints which are not uint256 could be changed to uint256 and only casted to the intended size when storing it.
More info at: ourzora/v3#125 (comment)

Just swapped the lend() function and consequent related tests resulting in: (...) Overall gas change: -11839 (-0.041%)
But there are many other functions (eg. createLoan) which could use such change, so the gas saving should be way more than that.

-- 2
cache borrowTicketContract at createLoan to save one SLOAD on a successful transaction.

-- 3
use cached previousInterestRate on calling _interestOwed

Overall gas change: -60 (-0.000%)

diff --git a/contracts/NFTLoanFacilitator.sol b/contracts/NFTLoanFacilitator.sol
index 46d6ef5..bb25958 100644
--- a/contracts/NFTLoanFacilitator.sol
+++ b/contracts/NFTLoanFacilitator.sol
@@ -165,6 +165,7 @@ contract NFTLoanFacilitator is Ownable, INFTLoanFacilitator {
             // will underflow if amount < previousAmount
             uint256 amountIncrease = amount - previousLoanAmount;
 
+            uint256 accumulatedInterest;
             {
                 uint256 previousInterestRate = loan.perAnumInterestRate;
                 uint256 previousDurationSeconds = loan.durationSeconds;
@@ -177,14 +178,14 @@ contract NFTLoanFacilitator is Ownable, INFTLoanFacilitator {
                 || (previousInterestRate != 0 // do not allow rate improvement if rate already 0
                     && previousInterestRate - (previousInterestRate * requiredImprovementRate / SCALAR) >= interestRate), 
                 "NFTLoanFacilitator: proposed terms must be better than existing terms");
-            }
 
-            uint256 accumulatedInterest = _interestOwed(
-                previousLoanAmount,
-                loan.lastAccumulatedTimestamp,
-                loan.perAnumInterestRate,
-                loan.accumulatedInterest
-            );
+                 = _interestOwed(
+                    previousLoanAmount,
+                    loan.lastAccumulatedTimestamp,
+                    previousInterestRate,
+                    loan.accumulatedInterest
+                );
+            }
             require(accumulatedInterest <= type(uint128).max,
             "NFTLoanFacilitator: accumulated interest exceeds uint128");

-- 4

cache loan.loanAmount on repayAndCloseLoan

testRepayInterestOwedExceedingUint128() (gas: -253 (-0.001%)) 
testRepayAndCloseSuccessful() (gas: -253 (-0.001%)) 
testRepayAndClose() (gas: -253 (-0.003%)) 
Overall gas change: -759 (-0.004%)
diff --git a/contracts/NFTLoanFacilitator.sol b/contracts/NFTLoanFacilitator.sol
index f1f570f..ff2e3f7 100644
--- a/contracts/NFTLoanFacilitator.sol
+++ b/contracts/NFTLoanFacilitator.sol
@@ -231,23 +231,24 @@ contract NFTLoanFacilitator is Ownable, INFTLoanFacilitator {
     /// See {INFTLoanFacilitator-repayAndCloseLoan}.
     function repayAndCloseLoan(uint256 loanId) external override notClosed(loanId) {
         Loan storage loan = loanInfo[loanId];
+        uint256 _loanAmount = loan.loanAmount;
 
         uint256 interest = _interestOwed(
-            loan.loanAmount,
+            _loanAmount,
             loan.lastAccumulatedTimestamp,
             loan.perAnumInterestRate,
             loan.accumulatedInterest
         );
         address lender = IERC721(lendTicketContract).ownerOf(loanId);
         loan.closed = true;
-        ERC20(loan.loanAssetContractAddress).safeTransferFrom(msg.sender, lender, interest + loan.loanAmount);
+        ERC20(loan.loanAssetContractAddress).safeTransferFrom(msg.sender, lender, interest + _loanAmount);
         IERC721(loan.collateralContractAddress).safeTransferFrom(
             address(this),
             IERC721(borrowTicketContract).ownerOf(loanId),
             loan.collateralTokenId
         );
 
-        emit Repay(loanId, msg.sender, lender, interest, loan.loanAmount);
+        emit Repay(loanId, msg.sender, lender, interest, _loanAmount);
         emit Close(loanId);
     }
@code423n4 code423n4 added bug Something isn't working G (Gas Optimization) labels Apr 5, 2022
code423n4 added a commit that referenced this issue Apr 5, 2022
@wilsoncusack
Copy link
Collaborator

  1. we would need then to check whether the passed param does not exceed the max value for the struct value, which erases gas gains. Not ok with just covering to e.g. uint32.max if it exceeds
  2. ack
  3. ack

@wilsoncusack wilsoncusack added the sponsor confirmed Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity") label Apr 8, 2022
@wilsoncusack
Copy link
Collaborator

@wilsoncusack wilsoncusack added the resolved Finding has been patched by sponsor (sponsor pls link to PR containing fix) label Apr 10, 2022
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) resolved Finding has been patched by sponsor (sponsor pls link to PR containing fix) sponsor confirmed Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
Projects
None yet
Development

No branches or pull requests

2 participants