From 92c45f0c5a75f2d17f808c4dee86f6b7434e2f54 Mon Sep 17 00:00:00 2001 From: androolloyd Date: Mon, 20 Nov 2023 11:33:15 -0400 Subject: [PATCH] updates to make the fuzzers into a pipeline (#75) * updates to make the fuzzers into a pipeline * chore snapshot * add optimizations for changing loan state, remove double encoding of data --- .gas-snapshot | 216 +++++++++++------------ src/Starport.sol | 56 ++++-- src/enforcers/BorrowerEnforcer.sol | 2 +- src/enforcers/BorrowerEnforcerBNPL.sol | 2 +- src/enforcers/LenderEnforcer.sol | 1 + test/StarportTest.sol | 1 + test/fuzz-testing/TestFuzzStarport.sol | 111 ++++++------ test/integration-testing/TestCaveats.sol | 27 +-- test/unit-testing/TestCustodian.sol | 3 +- 9 files changed, 232 insertions(+), 187 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 4729aad4..4091213e 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,144 +1,144 @@ -IntegrationTestCaveats:testOriginateUnapprovedFulfiller() (gas: 366712) -IntegrationTestCaveats:testOriginateWBorrowerApproval() (gas: 320478) -IntegrationTestCaveats:testOriginateWCaveats() (gas: 294572) -IntegrationTestCaveats:testOriginateWCaveatsExpired() (gas: 177232) -IntegrationTestCaveats:testOriginateWCaveatsIncrementedNonce() (gas: 205798) -IntegrationTestCaveats:testOriginateWCaveatsInvalidSalt() (gas: 300823) -IntegrationTestCaveats:testOriginateWCaveatsInvalidSaltManual() (gas: 179750) -IntegrationTestCaveats:testOriginateWLenderApproval() (gas: 320554) -IntegrationTestCaveats:testRefinanceAsLender() (gas: 1082795) -IntegrationTestCaveats:testRefinanceCaveatFailure() (gas: 434517) -IntegrationTestCaveats:testRefinanceLoanStartAtBlockTimestampInvalidLoan() (gas: 381921) -IntegrationTestCaveats:testRefinanceUnapprovedFulfiller() (gas: 489763) -IntegrationTestCaveats:testRefinanceWCaveatsInvalidSalt() (gas: 411188) -IntegrationTestCaveats:testRefinanceWLenderApproval() (gas: 431878) -ModuleTesting:testFixedTermDutchAuctionSettlement() (gas: 433286) -ModuleTesting:testFixedTermDutchAuctionSettlementGetSettlementAuctionExpired() (gas: 436153) -ModuleTesting:testFixedTermDutchAuctionSettlementNotValid() (gas: 432276) -ModuleTesting:testFixedTermDutchAuctionSettlementValid() (gas: 433097) -ModuleTesting:testModuleValidation() (gas: 1269927) +IntegrationTestCaveats:testOriginateUnapprovedFulfiller() (gas: 327195) +IntegrationTestCaveats:testOriginateWBorrowerApproval() (gas: 280767) +IntegrationTestCaveats:testOriginateWCaveatsAsBorrower() (gas: 302928) +IntegrationTestCaveats:testOriginateWCaveatsExpired() (gas: 157332) +IntegrationTestCaveats:testOriginateWCaveatsIncrementedNonce() (gas: 166063) +IntegrationTestCaveats:testOriginateWCaveatsInvalidSalt() (gas: 281012) +IntegrationTestCaveats:testOriginateWCaveatsInvalidSaltManual() (gas: 139972) +IntegrationTestCaveats:testOriginateWLenderApproval() (gas: 280843) +IntegrationTestCaveats:testRefinanceAsLender() (gas: 1043237) +IntegrationTestCaveats:testRefinanceCaveatFailure() (gas: 395324) +IntegrationTestCaveats:testRefinanceLoanStartAtBlockTimestampInvalidLoan() (gas: 342658) +IntegrationTestCaveats:testRefinanceUnapprovedFulfiller() (gas: 450558) +IntegrationTestCaveats:testRefinanceWCaveatsInvalidSalt() (gas: 371779) +IntegrationTestCaveats:testRefinanceWLenderApproval() (gas: 392364) +ModuleTesting:testFixedTermDutchAuctionSettlement() (gas: 433591) +ModuleTesting:testFixedTermDutchAuctionSettlementGetSettlementAuctionExpired() (gas: 436458) +ModuleTesting:testFixedTermDutchAuctionSettlementNotValid() (gas: 432581) +ModuleTesting:testFixedTermDutchAuctionSettlementValid() (gas: 433402) +ModuleTesting:testModuleValidation() (gas: 1270232) PausableNonReentrantImpl:test() (gas: 2442) PausableNonReentrantImpl:testReentrancy() (gas: 2735) -TestBorrowerEnforcer:testBERevertAdditionalTransfersFromBorrower() (gas: 76218) -TestBorrowerEnforcer:testBERevertInvalidLoanTerms() (gas: 81026) -TestBorrowerEnforcer:testBEValidLoanTerms() (gas: 72021) -TestBorrowerEnforcer:testBEValidLoanTermsAnyIssuer() (gas: 72085) -TestCustodian:testCannotLazyMintTwice() (gas: 78796) +TestBorrowerEnforcer:testBERevertAdditionalTransfersFromBorrower() (gas: 76434) +TestBorrowerEnforcer:testBERevertInvalidLoanTerms() (gas: 81242) +TestBorrowerEnforcer:testBEValidLoanTerms() (gas: 72237) +TestBorrowerEnforcer:testBEValidLoanTermsAnyIssuer() (gas: 72301) +TestCustodian:testCannotLazyMintTwice() (gas: 78788) TestCustodian:testCannotMintInvalidLoanInvalidCustodian() (gas: 69031) -TestCustodian:testCannotMintInvalidLoanValidCustodian() (gas: 74555) +TestCustodian:testCannotMintInvalidLoanValidCustodian() (gas: 74547) TestCustodian:testCustodySelector() (gas: 2861655) TestCustodian:testDefaultCustodySelectorRevert() (gas: 72312) -TestCustodian:testGenerateOrderInvalidPostRepayment() (gas: 173056) -TestCustodian:testGenerateOrderInvalidPostSettlement() (gas: 163179) -TestCustodian:testGenerateOrderRepay() (gas: 177211) -TestCustodian:testGenerateOrderRepayAsRepayApprovedBorrower() (gas: 193680) -TestCustodian:testGenerateOrderRepayERC1155AndERC20() (gas: 868121) -TestCustodian:testGenerateOrderRepayERC1155AndERC20HandlerAuthorized() (gas: 797782) +TestCustodian:testGenerateOrderInvalidPostRepayment() (gas: 172910) +TestCustodian:testGenerateOrderInvalidPostSettlement() (gas: 163033) +TestCustodian:testGenerateOrderRepay() (gas: 177065) +TestCustodian:testGenerateOrderRepayAsRepayApprovedBorrower() (gas: 193534) +TestCustodian:testGenerateOrderRepayERC1155AndERC20() (gas: 868007) +TestCustodian:testGenerateOrderRepayERC1155AndERC20HandlerAuthorized() (gas: 797668) TestCustodian:testGenerateOrderRepayInvalidHookAddress() (gas: 97601) TestCustodian:testGenerateOrderRepayInvalidHookReturnType() (gas: 91984) TestCustodian:testGenerateOrderRepayNotBorrower() (gas: 106839) -TestCustodian:testGenerateOrderSettlement() (gas: 154934) -TestCustodian:testGenerateOrderSettlementHandlerAuthorized() (gas: 160331) -TestCustodian:testGenerateOrderSettlementNoActiveLoan() (gas: 163342) +TestCustodian:testGenerateOrderSettlement() (gas: 154788) +TestCustodian:testGenerateOrderSettlementHandlerAuthorized() (gas: 160185) +TestCustodian:testGenerateOrderSettlementNoActiveLoan() (gas: 163250) TestCustodian:testGenerateOrderSettlementUnauthorized() (gas: 101813) -TestCustodian:testGenerateOrdersWithLoanStartAtBlockTimestampInvalidLoan() (gas: 458156) +TestCustodian:testGenerateOrdersWithLoanStartAtBlockTimestampInvalidLoan() (gas: 458245) TestCustodian:testGetBorrower() (gas: 78641) -TestCustodian:testInvalidAction() (gas: 173284) -TestCustodian:testInvalidActionRepayInActiveLoan() (gas: 130104) -TestCustodian:testInvalidActionSettleActiveLoan() (gas: 130086) +TestCustodian:testInvalidAction() (gas: 173196) +TestCustodian:testInvalidActionRepayInActiveLoan() (gas: 130060) +TestCustodian:testInvalidActionSettleActiveLoan() (gas: 130042) TestCustodian:testInvalidEncodedData() (gas: 26192) -TestCustodian:testMintWithApprovalSetAsBorrower() (gas: 359900) +TestCustodian:testMintWithApprovalSetAsBorrower() (gas: 359984) TestCustodian:testMintWithApprovalSetAsBorrowerInvalidLoan() (gas: 60792) -TestCustodian:testMintWithApprovalSetNotAuthorized() (gas: 76759) +TestCustodian:testMintWithApprovalSetNotAuthorized() (gas: 76751) TestCustodian:testName() (gas: 7121) TestCustodian:testNonPayableFunctions() (gas: 215173) TestCustodian:testOnlySeaport() (gas: 17829) -TestCustodian:testPreviewOrderNoActiveLoan() (gas: 105805) -TestCustodian:testPreviewOrderRepay() (gas: 230156) -TestCustodian:testPreviewOrderSettlement() (gas: 191848) -TestCustodian:testPreviewOrderSettlementInvalidFufliller() (gas: 108234) -TestCustodian:testPreviewOrderSettlementInvalidRepayer() (gas: 116961) -TestCustodian:testRatifyOrder() (gas: 184032) +TestCustodian:testPreviewOrderNoActiveLoan() (gas: 105761) +TestCustodian:testPreviewOrderRepay() (gas: 229966) +TestCustodian:testPreviewOrderSettlement() (gas: 191658) +TestCustodian:testPreviewOrderSettlementInvalidFufliller() (gas: 108190) +TestCustodian:testPreviewOrderSettlementInvalidRepayer() (gas: 116917) +TestCustodian:testRatifyOrder() (gas: 183886) TestCustodian:testSeaportMetadata() (gas: 8632) TestCustodian:testSupportsInterface() (gas: 9428) TestCustodian:testSymbol() (gas: 7105) TestCustodian:testTokenURI() (gas: 67024) TestCustodian:testTokenURIInvalidLoan() (gas: 13151) -TestLenderEnforcer:testLERevertAdditionalTransfersFromLender() (gas: 76210) -TestLenderEnforcer:testLERevertInvalidLoanTerms() (gas: 80962) -TestLenderEnforcer:testLEValidLoanTerms() (gas: 71955) -TestLenderEnforcer:testLEValidLoanTermsAnyBorrower() (gas: 72087) -TestLenderEnforcer:testLEValidLoanTermsWithAdditionalTransfers() (gas: 73310) -TestLoanCombinations:testLoan20For721SimpleInterestDutchFixedRepay() (gas: 586757) -TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 593970) -TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 585051) -TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 574861) -TestNewLoan:testBuyNowPayLater() (gas: 2869372) +TestLenderEnforcer:testLERevertAdditionalTransfersFromLender() (gas: 76426) +TestLenderEnforcer:testLERevertInvalidLoanTerms() (gas: 81178) +TestLenderEnforcer:testLEValidLoanTerms() (gas: 72171) +TestLenderEnforcer:testLEValidLoanTermsAnyBorrower() (gas: 72303) +TestLenderEnforcer:testLEValidLoanTermsWithAdditionalTransfers() (gas: 73526) +TestLoanCombinations:testLoan20For721SimpleInterestDutchFixedRepay() (gas: 586872) +TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 594085) +TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 585158) +TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 574976) +TestNewLoan:testBuyNowPayLater() (gas: 2869677) TestNewLoan:testInvalidSenderBNPL() (gas: 1613720) TestNewLoan:testInvalidUserDataHashBNPL() (gas: 1616299) -TestNewLoan:testNewLoanAs1271ProxyAccountSender() (gas: 861278) -TestNewLoan:testNewLoanAs1271ProxyAccountThirdPartyFiller() (gas: 870656) -TestNewLoan:testNewLoanERC721CollateralDefaultTerms2() (gas: 424450) -TestNewLoan:testNewLoanRefinance() (gas: 583073) -TestNewLoan:testNewLoanViaOriginatorBorrowerApprovalAndLenderApproval() (gas: 325542) -TestNewLoan:testNewLoanViaOriginatorLenderApproval() (gas: 381839) -TestNewLoan:testSettleLoan() (gas: 636143) +TestNewLoan:testNewLoanAs1271ProxyAccountSender() (gas: 861299) +TestNewLoan:testNewLoanAs1271ProxyAccountThirdPartyFiller() (gas: 870929) +TestNewLoan:testNewLoanERC721CollateralDefaultTerms2() (gas: 424755) +TestNewLoan:testNewLoanRefinance() (gas: 583149) +TestNewLoan:testNewLoanViaOriginatorBorrowerApprovalAndLenderApproval() (gas: 325459) +TestNewLoan:testNewLoanViaOriginatorLenderApproval() (gas: 381950) +TestNewLoan:testSettleLoan() (gas: 636302) TestPausableNonReentrant:testNotOwner() (gas: 21254) TestPausableNonReentrant:testPauseAndUnpause() (gas: 22555) TestPausableNonReentrant:testReentrancy() (gas: 15360) TestPausableNonReentrant:testUnpauseWhenNotPaused() (gas: 12582) -TestRepayLoan:testRepayLoanApprovedRepayer() (gas: 658479) -TestRepayLoan:testRepayLoanBase() (gas: 594682) -TestRepayLoan:testRepayLoanGenerateOrderNotSeaport() (gas: 433481) -TestRepayLoan:testRepayLoanInSettlement() (gas: 580179) -TestRepayLoan:testRepayLoanInvalidRepayer() (gas: 598608) -TestRepayLoan:testRepayLoanThatDoesNotExist() (gas: 853185) +TestRepayLoan:testRepayLoanApprovedRepayer() (gas: 658586) +TestRepayLoan:testRepayLoanBase() (gas: 594797) +TestRepayLoan:testRepayLoanGenerateOrderNotSeaport() (gas: 433786) +TestRepayLoan:testRepayLoanInSettlement() (gas: 580440) +TestRepayLoan:testRepayLoanInvalidRepayer() (gas: 598869) +TestRepayLoan:testRepayLoanThatDoesNotExist() (gas: 853072) TestSimpleInterestPricing:test_calculateInterest() (gas: 895930) TestSimpleInterestPricing:test_getPaymentConsideration() (gas: 943140) TestSimpleInterestPricing:test_getRefinanceConsideration() (gas: 933907) -TestStarport:testActive() (gas: 69320) -TestStarport:testAdditionalTransfers() (gas: 298120) -TestStarport:testAdditionalTransfersOriginate() (gas: 272838) -TestStarport:testAdditionalTransfersRefinance() (gas: 211072) -TestStarport:testApplyRefinanceConsiderationToLoanMalformed() (gas: 121896) -TestStarport:testCannotIssueSameLoanTwice() (gas: 358910) -TestStarport:testCannotOriginateWhilePaused() (gas: 73457) -TestStarport:testCannotSettleInvalidLoan() (gas: 74915) +TestStarport:testActive() (gas: 69312) +TestStarport:testAdditionalTransfers() (gas: 298209) +TestStarport:testAdditionalTransfersOriginate() (gas: 272927) +TestStarport:testAdditionalTransfersRefinance() (gas: 210821) +TestStarport:testApplyRefinanceConsiderationToLoanMalformed() (gas: 121962) +TestStarport:testCannotIssueSameLoanTwice() (gas: 359137) +TestStarport:testCannotOriginateWhilePaused() (gas: 73479) +TestStarport:testCannotSettleInvalidLoan() (gas: 74823) TestStarport:testCannotSettleUnlessValidCustodian() (gas: 70985) TestStarport:testCaveatEnforcerRevert() (gas: 99214) -TestStarport:testDefaultFeeRake() (gas: 357730) -TestStarport:testDefaultFeeRakeExoticDebt() (gas: 367863) -TestStarport:testExoticDebtWithNoCaveatsNotAsBorrower() (gas: 374121) -TestStarport:testIncrementCaveatNonce() (gas: 35208) -TestStarport:testInitializedFlagSetProperly() (gas: 67393) -TestStarport:testInvalidAdditionalTransfersOriginate() (gas: 227780) -TestStarport:testInvalidAdditionalTransfersRefinance() (gas: 163706) -TestStarport:testInvalidAmountCollateral() (gas: 163345) -TestStarport:testInvalidAmountCollateral721() (gas: 163345) -TestStarport:testInvalidItemType() (gas: 149293) -TestStarport:testInvalidTransferLengthCollateral() (gas: 151635) -TestStarport:testInvalidTransferLengthDebt() (gas: 173302) -TestStarport:testInvalidateCaveatSalt() (gas: 33494) -TestStarport:testNonDefaultCustodianCustodyCallFails() (gas: 261553) -TestStarport:testNonDefaultCustodianCustodyCallSuccess() (gas: 287766) -TestStarport:testNonPayableFunctions() (gas: 112043) -TestStarport:testOverrideFeeRake() (gas: 354048) -TestStarport:testPause() (gas: 18093) -TestStarport:testRefinancePostRepaymentFails() (gas: 120803) -TestStarport:testTokenNoCodeCollateral() (gas: 148106) -TestStarport:testTokenNoCodeDebt() (gas: 178379) -TestStarport:testUnpause() (gas: 17198) +TestStarport:testDefaultFeeRake() (gas: 357863) +TestStarport:testDefaultFeeRakeExoticDebt() (gas: 367996) +TestStarport:testExoticDebtWithNoCaveatsNotAsBorrower() (gas: 374210) +TestStarport:testIncrementCaveatNonce() (gas: 35230) +TestStarport:testInitializedFlagSetProperly() (gas: 67349) +TestStarport:testInvalidAdditionalTransfersOriginate() (gas: 227996) +TestStarport:testInvalidAdditionalTransfersRefinance() (gas: 163582) +TestStarport:testInvalidAmountCollateral() (gas: 163561) +TestStarport:testInvalidAmountCollateral721() (gas: 163561) +TestStarport:testInvalidItemType() (gas: 149509) +TestStarport:testInvalidTransferLengthCollateral() (gas: 151851) +TestStarport:testInvalidTransferLengthDebt() (gas: 173518) +TestStarport:testInvalidateCaveatSalt() (gas: 33516) +TestStarport:testNonDefaultCustodianCustodyCallFails() (gas: 261642) +TestStarport:testNonDefaultCustodianCustodyCallSuccess() (gas: 287855) +TestStarport:testNonPayableFunctions() (gas: 112065) +TestStarport:testOverrideFeeRake() (gas: 354203) +TestStarport:testPause() (gas: 18115) +TestStarport:testRefinancePostRepaymentFails() (gas: 120679) +TestStarport:testTokenNoCodeCollateral() (gas: 148322) +TestStarport:testTokenNoCodeDebt() (gas: 178595) +TestStarport:testUnpause() (gas: 17220) TestStrategistOriginator:testEncodeWithAccountCounter() (gas: 12307) TestStrategistOriginator:testGetStrategistData() (gas: 1489933) TestStrategistOriginator:testIncrementCounterAsStrategist() (gas: 18676) TestStrategistOriginator:testIncrementCounterNotAuthorized() (gas: 13401) -TestStrategistOriginator:testInvalidCollateral() (gas: 209797) -TestStrategistOriginator:testInvalidDeadline() (gas: 215512) -TestStrategistOriginator:testInvalidDebt() (gas: 211435) -TestStrategistOriginator:testInvalidDebtAmountAskingMoreThanOffered() (gas: 211796) -TestStrategistOriginator:testInvalidDebtAmountOfferingZero() (gas: 212095) -TestStrategistOriginator:testInvalidDebtAmountRequestingZero() (gas: 212049) -TestStrategistOriginator:testInvalidDebtLength() (gas: 210678) -TestStrategistOriginator:testInvalidOffer() (gas: 424408) -TestStrategistOriginator:testInvalidSigner() (gas: 214006) +TestStrategistOriginator:testInvalidCollateral() (gas: 209819) +TestStrategistOriginator:testInvalidDeadline() (gas: 215534) +TestStrategistOriginator:testInvalidDebt() (gas: 211457) +TestStrategistOriginator:testInvalidDebtAmountAskingMoreThanOffered() (gas: 211818) +TestStrategistOriginator:testInvalidDebtAmountOfferingZero() (gas: 212117) +TestStrategistOriginator:testInvalidDebtAmountRequestingZero() (gas: 212071) +TestStrategistOriginator:testInvalidDebtLength() (gas: 210700) +TestStrategistOriginator:testInvalidOffer() (gas: 424519) +TestStrategistOriginator:testInvalidSigner() (gas: 214028) TestStrategistOriginator:testSetStrategist() (gas: 17796) \ No newline at end of file diff --git a/src/Starport.sol b/src/Starport.sol index 83b8013a..8c08a40a 100644 --- a/src/Starport.sol +++ b/src/Starport.sol @@ -42,10 +42,9 @@ contract Starport is PausableNonReentrant { BORROWER, LENDER } - enum FieldFlags { - INACTIVE, - ACTIVE - } + + uint256 public constant LOAN_INACTIVE_FLAG = 0x0; + uint256 public constant LOAN_ACTIVE_FLAG = 0x1; struct Terms { address status; //the address of the status module @@ -411,7 +410,7 @@ contract Starport is PausableNonReentrant { * @return True if the loan is active */ function active(uint256 loanId) public view returns (bool) { - return loanState[loanId] == uint256(FieldFlags.ACTIVE); + return loanState[loanId] == LOAN_ACTIVE_FLAG; } /** @@ -420,7 +419,7 @@ contract Starport is PausableNonReentrant { * @return True if the loan is inactive */ function inactive(uint256 loanId) public view returns (bool) { - return loanState[loanId] == uint256(FieldFlags.INACTIVE); + return loanState[loanId] == LOAN_INACTIVE_FLAG; } /** @@ -435,13 +434,28 @@ contract Starport is PausableNonReentrant { _settle(loan); } + bytes32 private constant _INVALID_LOAN = 0x045f33d100000000000000000000000000000000000000000000000000000000; + bytes32 private constant _LOAN_EXISTS = 0x14ec57fc00000000000000000000000000000000000000000000000000000000; + function _settle(Loan memory loan) internal { uint256 loanId = loan.getId(); - if (inactive(loanId)) { - revert InvalidLoan(); - } + assembly { + mstore(0x0, loanId) + mstore(0x20, loanState.slot) + + // loanState[loanId] - loanState[loanId] = uint256(FieldFlags.INACTIVE); + let loc := keccak256(0x0, 0x40) + + // if (inactive(loanId)) { + if iszero(sload(loc)) { + //revert InvalidLoan() + mstore(0x0, _INVALID_LOAN) + revert(0x0, 0x04) + } + + sstore(loc, LOAN_INACTIVE_FLAG) + } emit Close(loanId); } @@ -529,11 +543,25 @@ contract Starport is PausableNonReentrant { loan.originator = loan.originator != address(0) ? loan.originator : msg.sender; uint256 loanId = loan.getId(); - if (active(loanId)) { - revert LoanExists(); - } + // if (active(loanId)) { + // revert LoanExists(); + // } + // + assembly { + mstore(0x0, loanId) + mstore(0x20, loanState.slot) + + //loanState[loanId] + let loc := keccak256(0x0, 0x40) + // if (active(loanId)) + if iszero(iszero(sload(loc))) { + //revert LoanExists() + mstore(0x0, _LOAN_EXISTS) + revert(0x0, 0x04) + } - loanState[loanId] = uint256(FieldFlags.ACTIVE); + sstore(loc, LOAN_ACTIVE_FLAG) + } emit Open(loanId, loan); } } diff --git a/src/enforcers/BorrowerEnforcer.sol b/src/enforcers/BorrowerEnforcer.sol index 6c72aba9..15df3bb9 100644 --- a/src/enforcers/BorrowerEnforcer.sol +++ b/src/enforcers/BorrowerEnforcer.sol @@ -36,7 +36,7 @@ contract BorrowerEnforcer is CaveatEnforcer { Details memory details ) internal pure { details.loan.issuer = loan.issuer; - + details.loan.originator = loan.originator; if (keccak256(abi.encode(loan)) != keccak256(abi.encode(details.loan))) revert InvalidLoanTerms(); if (additionalTransfers.length > 0) { diff --git a/src/enforcers/BorrowerEnforcerBNPL.sol b/src/enforcers/BorrowerEnforcerBNPL.sol index 52607cef..8fb6fa69 100644 --- a/src/enforcers/BorrowerEnforcerBNPL.sol +++ b/src/enforcers/BorrowerEnforcerBNPL.sol @@ -38,7 +38,7 @@ contract BorrowerEnforcerBNPL is CaveatEnforcer { revert BorrowerOnlyEnforcer(); } details.loan.issuer = loan.issuer; - + details.loan.originator = loan.originator; if (loanHash != keccak256(abi.encode(details.loan))) { revert InvalidLoanTerms(); } diff --git a/src/enforcers/LenderEnforcer.sol b/src/enforcers/LenderEnforcer.sol index 02e94818..677eb6a8 100644 --- a/src/enforcers/LenderEnforcer.sol +++ b/src/enforcers/LenderEnforcer.sol @@ -35,6 +35,7 @@ contract LenderEnforcer is CaveatEnforcer { Details memory details ) internal pure { details.loan.borrower = loan.borrower; + details.loan.originator = loan.originator; if (keccak256(abi.encode(loan)) != keccak256(abi.encode(details.loan))) { revert InvalidLoanTerms(); diff --git a/test/StarportTest.sol b/test/StarportTest.sol index 5954a95f..1b998b91 100644 --- a/test/StarportTest.sol +++ b/test/StarportTest.sol @@ -361,6 +361,7 @@ contract StarportTest is BaseOrderTest { ) internal returns (Starport.Loan memory) { (CaveatEnforcer.SignedCaveats memory borrowerCaveat, CaveatEnforcer.SignedCaveats memory lenderCaveat) = newLoanOriginationSetup(loan, borrower, borrowerSalt, lender, lenderSalt, invalidateLender); + vm.roll(1); return newLoan(loan, borrowerCaveat, lenderCaveat, fulfiller); } diff --git a/test/fuzz-testing/TestFuzzStarport.sol b/test/fuzz-testing/TestFuzzStarport.sol index 82eedb50..bc7b4f12 100644 --- a/test/fuzz-testing/TestFuzzStarport.sol +++ b/test/fuzz-testing/TestFuzzStarport.sol @@ -9,7 +9,7 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { using FixedPointMathLib for uint256; using {StarportLib.getId} for Starport.Loan; - function setUp() public override { + function setUp() public virtual override { super.setUp(); vm.warp(100_000); @@ -50,7 +50,8 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { vm.stopPrank(); } - function boundPricingData(uint256 min) internal view returns (bytes memory pricingData) { + function boundPricingData(bytes memory boundPricingData) internal view virtual returns (bytes memory pricingData) { + uint256 min = abi.decode(boundPricingData, (uint256)); BasePricing.Details memory details = BasePricing.Details({ rate: _boundMax(min, (uint256(1e16) * 150)), carryRate: _boundMax(0, uint256((1e16 * 100))), @@ -59,13 +60,18 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { pricingData = abi.encode(details); } - function boundStatusData() internal view returns (bytes memory statusData) { + function boundStatusData(bytes memory boundStatusData) internal view virtual returns (bytes memory statusData) { FixedTermStatus.Details memory boundDetails = FixedTermStatus.Details({loanDuration: _boundMax(1 hours, 1095 days)}); statusData = abi.encode(boundDetails); } - function boundSettlementData() internal view returns (bytes memory settlementData) { + function boundSettlementData(bytes memory boundSettlementData) + internal + view + virtual + returns (bytes memory settlementData) + { DutchAuctionSettlement.Details memory boundDetails = DutchAuctionSettlement.Details({ startingPrice: _boundMax(501 ether, 1000 ether), endingPrice: _boundMax(1 ether, 500 ether), @@ -74,13 +80,19 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { settlementData = abi.encode(boundDetails); } - function boundFuzzLenderTerms(LoanBounds memory loanBounds) internal view returns (Starport.Terms memory terms) { + function boundFuzzLenderTerms(bytes memory loanBoundsData) + internal + view + virtual + returns (Starport.Terms memory terms) + { + LoanBounds memory loanBounds = abi.decode(loanBoundsData, (LoanBounds)); terms.status = address(status); terms.settlement = address(settlement); terms.pricing = address(pricing); - terms.pricingData = boundPricingData(loanBounds.minPricing); - terms.statusData = boundStatusData(); - terms.settlementData = boundSettlementData(); + terms.pricingData = boundPricingData(abi.encode(loanBounds.minPricing)); + terms.statusData = boundStatusData(""); + terms.settlementData = boundSettlementData(""); } struct FuzzLoan { @@ -116,12 +128,14 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { uint256 skipTime; } - function boundFuzzLoan(FuzzLoan memory params, LoanBounds memory loanBounds) + function boundFuzzLoan(FuzzLoan memory params, bytes memory loanBoundsData) internal + virtual returns (Starport.Loan memory loan) { + LoanBounds memory loanBounds = abi.decode(loanBoundsData, (LoanBounds)); uint256 length = _boundMax(1, 4); - loan.terms = boundFuzzLenderTerms(loanBounds); + loan.terms = boundFuzzLenderTerms(loanBoundsData); uint256 i = 0; if (length > params.collateral.length) { length = params.collateral.length; @@ -136,7 +150,7 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { debt[0] = SpentItem({ itemType: ItemType.ERC20, identifier: 0, - amount: _boundMax(params.debtAmount, type(uint128).max), + amount: _boundMax(params.debtAmount, type(uint112).max), token: address(erc20s[1]) }); loan.debt = debt; @@ -146,8 +160,7 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { return loan; } - function willArithmeticOverflow(Starport.Loan memory loan) internal view returns (bool) { - FixedTermStatus.Details memory statusDetails = abi.decode(loan.terms.statusData, (FixedTermStatus.Details)); + function willArithmeticOverflow(Starport.Loan memory loan) internal view virtual returns (bool) { BasePricing.Details memory pricingDetails = abi.decode(loan.terms.pricingData, (BasePricing.Details)); try BasePricing(loan.terms.pricing).getPaymentConsideration(loan) returns ( SpentItem[] memory repayConsideration, SpentItem[] memory carryConsideration @@ -164,8 +177,8 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { } } - function testFuzzNewOrigination(FuzzLoan memory params) public { - fuzzNewLoanOrigination(params, LoanBounds(0)); + function testFuzzNewOrigination(FuzzLoan memory params) public virtual { + _generateGoodLoan(params); } struct LoanBounds { @@ -178,12 +191,12 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { uint256[] borrowerReceivedDebt; } - function fuzzNewLoanOrigination(FuzzLoan memory params, LoanBounds memory loanBounds) + function fuzzNewLoanOrigination(FuzzLoan memory params, bytes memory loanBoundsData) internal returns (Starport.Loan memory goodLoan) { vm.assume(params.collateral.length > 1); - Starport.Loan memory loan = boundFuzzLoan(params, loanBounds); + Starport.Loan memory loan = boundFuzzLoan(params, loanBoundsData); vm.assume(!willArithmeticOverflow(loan)); uint88 feeRake = uint88(_boundMax(0, 1e17)); @@ -221,9 +234,9 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { Fuzz.SpentItem[10] memory collateral, Fuzz.SpentItem[10] memory debt, address[3] memory badAddresses - ) public returns (Starport.Loan memory loan) { + ) public virtual returns (Starport.Loan memory loan) { uint256 length = _boundMin(0, collateral.length); - loan.terms = boundFuzzLenderTerms(LoanBounds(0)); + loan.terms = boundFuzzLenderTerms(abi.encode(LoanBounds(0))); uint256 i = 0; SpentItem[] memory ret = new SpentItem[](length); @@ -255,25 +268,19 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { } function testFuzzCustodianGeneratePreviewOrder(FuzzCustodian memory params) public { - // Starport.Loan memory badLoan = boundBadLoan(params.repayCollateral, params.repayDebt, params.badAddresses); - Starport.Loan memory goodLoan = fuzzNewLoanOrigination(params.origination, LoanBounds(0)); - - // badLoan.collateral = goodLoan.collateral; - // badLoan.debt = goodLoan.debt; - // badLoan.custodian = goodLoan.custodian; + Starport.Loan memory goodLoan = _generateGoodLoan(params.origination); Custodian.Command memory cmd; - uint256 loanDuration = abi.decode(goodLoan.terms.statusData, (FixedTermStatus.Details)).loanDuration; if (params.willRepay) { - skip(loanDuration - 1); + _skipToRepayment(goodLoan); if (!params.wrongCommand) { cmd = Custodian.Command(Actions.Repayment, goodLoan, ""); } else { cmd = Custodian.Command(Actions.Settlement, goodLoan, ""); } } else { - skip(loanDuration + 1); + _skipToSettlement(goodLoan); if (!params.wrongCommand) { cmd = Custodian.Command(Actions.Settlement, goodLoan, ""); } else { @@ -302,7 +309,7 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { function testFuzzLoanState(FuzzRepaymentLoan memory params) public { Starport.Loan memory badLoan = boundBadLoan(params.repayCollateral, params.repayDebt, params.badAddresses); - Starport.Loan memory goodLoan = fuzzNewLoanOrigination(params.origination, LoanBounds(0)); + Starport.Loan memory goodLoan = _generateGoodLoan(params.origination); badLoan.start = goodLoan.start; badLoan.originator = goodLoan.originator; @@ -316,7 +323,7 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { function testFuzzRepaymentFails(FuzzRepaymentLoan memory params) public { Starport.Loan memory badLoan = boundBadLoan(params.repayCollateral, params.repayDebt, params.badAddresses); - Starport.Loan memory goodLoan = fuzzNewLoanOrigination(params.origination, LoanBounds(0)); + Starport.Loan memory goodLoan = _generateGoodLoan(params.origination); badLoan.collateral = goodLoan.collateral; badLoan.debt = goodLoan.debt; @@ -355,8 +362,8 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { } function testFuzzRepaymentSuccess(FuzzRepaymentLoan memory params) public { - Starport.Loan memory goodLoan = fuzzNewLoanOrigination(params.origination, LoanBounds(0)); - skip(_boundMax(1, abi.decode(goodLoan.terms.statusData, (FixedTermStatus.Details)).loanDuration - 1)); + Starport.Loan memory goodLoan = _generateGoodLoan(params.origination); + _skipToRepayment(goodLoan); (SpentItem[] memory offer, ReceivedItem[] memory paymentConsideration) = Custodian(payable(goodLoan.custodian)) .previewOrder( @@ -394,19 +401,13 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { function testFuzzSettlementFails(FuzzRepaymentLoan memory params) public { Starport.Loan memory badLoan = boundBadLoan(params.repayCollateral, params.repayDebt, params.badAddresses); - Starport.Loan memory goodLoan = fuzzNewLoanOrigination(params.origination, LoanBounds(0)); + Starport.Loan memory goodLoan = _generateGoodLoan(params.origination); badLoan.collateral = goodLoan.collateral; badLoan.debt = goodLoan.debt; badLoan.custodian = goodLoan.custodian; - skip( - _bound( - params.skipTime, - abi.decode(goodLoan.terms.statusData, (FixedTermStatus.Details)).loanDuration, - 1000 days - ) - ); + _skipToSettlement(goodLoan); (SpentItem[] memory offer, ReceivedItem[] memory paymentConsideration) = Custodian(payable(goodLoan.custodian)) .previewOrder( @@ -440,20 +441,28 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { }); } - function testFuzzSettlementSuccess(FuzzSettleLoan memory params) public { - Starport.Loan memory goodLoan = fuzzNewLoanOrigination(params.origination, LoanBounds(0)); + function _generateGoodLoan(FuzzLoan memory params) internal virtual returns (Starport.Loan memory) { + return fuzzNewLoanOrigination(params, abi.encode(LoanBounds(0))); + } - address filler = _toAddress(_boundMin(_toUint(params.origination.fulfiller), 100)); - vm.assume(filler.code.length == 0); + function _skipToSettlement(Starport.Loan memory goodLoan) internal virtual { FixedTermStatus.Details memory statusDetails = abi.decode(goodLoan.terms.statusData, (FixedTermStatus.Details)); skip( - _bound( - params.skipTime, - abi.decode(goodLoan.terms.statusData, (FixedTermStatus.Details)).loanDuration, - uint256(1000 days) - ) + _bound(0, abi.decode(goodLoan.terms.statusData, (FixedTermStatus.Details)).loanDuration, uint256(1000 days)) ); + } + + function _skipToRepayment(Starport.Loan memory goodLoan) internal virtual { + skip(_boundMax(1, abi.decode(goodLoan.terms.statusData, (FixedTermStatus.Details)).loanDuration - 1)); + } + + function testFuzzSettlementSuccess(FuzzSettleLoan memory params) public virtual { + Starport.Loan memory goodLoan = _generateGoodLoan(params.origination); + + address filler = _toAddress(_boundMin(_toUint(params.origination.fulfiller), 100)); + vm.assume(filler.code.length == 0); + _skipToSettlement(goodLoan); (SpentItem[] memory offer, ReceivedItem[] memory paymentConsideration) = Custodian(payable(goodLoan.custodian)) .previewOrder( address(consideration), @@ -488,8 +497,8 @@ contract TestFuzzStarport is StarportTest, Bound, DeepEq { vm.stopPrank(); } - function testFuzzRefinance(FuzzRefinanceLoan memory params) public { - Starport.Loan memory goodLoan = fuzzNewLoanOrigination(params.origination, LoanBounds(1)); + function testFuzzRefinance(FuzzRefinanceLoan memory params) public virtual { + Starport.Loan memory goodLoan = fuzzNewLoanOrigination(params.origination, abi.encode(LoanBounds(1))); uint256 oldRate = abi.decode(goodLoan.terms.pricingData, (BasePricing.Details)).rate; diff --git a/test/integration-testing/TestCaveats.sol b/test/integration-testing/TestCaveats.sol index 68d6b0fe..4509d283 100644 --- a/test/integration-testing/TestCaveats.sol +++ b/test/integration-testing/TestCaveats.sol @@ -14,22 +14,27 @@ import "forge-std/console.sol"; contract IntegrationTestCaveats is StarportTest, DeepEq, MockCall { event LogLoan(Starport.Loan loan); - function testOriginateWCaveats() public { + using Cast for *; + + Starport.Loan activeLoan; + + function setUp() public override { + super.setUp(); Starport.Loan memory loan = generateDefaultLoanTerms(); + loan.toStorage(activeLoan); + _setApprovalsForSpentItems(loan.borrower, loan.collateral); + _setApprovalsForSpentItems(loan.issuer, loan.debt); + } - _setApprovalsForSpentItems(borrower.addr, loan.collateral); + function testOriginateWCaveatsAsBorrower() public { + CaveatEnforcer.SignedCaveats memory borrowerCaveat; + CaveatEnforcer.SignedCaveats memory lenderCaveat; - CaveatEnforcer.SignedCaveats memory lenderCaveat = getLenderSignedCaveat({ - details: LenderEnforcer.Details({loan: loan}), - signer: lender, - salt: bytes32(0), - enforcer: address(lenderEnforcer) - }); + borrowerCaveat = _generateSignedCaveatBorrower(activeLoan, borrower, bytes32(0)); - _setApprovalsForSpentItems(lender.addr, loan.debt); + lenderCaveat = _generateSignedCaveatLender(activeLoan, lender, bytes32(0), false); - vm.prank(loan.borrower); - SP.originate(new AdditionalTransfer[](0), _emptyCaveat(), lenderCaveat, loan); + newLoan(activeLoan, borrowerCaveat, lenderCaveat, borrower.addr); } function testOriginateWCaveatsInvalidSalt() public { diff --git a/test/unit-testing/TestCustodian.sol b/test/unit-testing/TestCustodian.sol index fa937673..e47cecee 100644 --- a/test/unit-testing/TestCustodian.sol +++ b/test/unit-testing/TestCustodian.sol @@ -116,9 +116,10 @@ contract TestCustodian is StarportTest, DeepEq, MockCall { function testMintWithApprovalSetAsBorrower() public { Starport.Loan memory loan = generateDefaultLoanTerms(); loan.collateral[0].identifier = uint256(3); + + newLoan(loan, bytes32(msg.sig), bytes32(msg.sig), borrower.addr); loan.start = block.timestamp; loan.originator = borrower.addr; - newLoan(loan, bytes32(msg.sig), bytes32(msg.sig), borrower.addr); // vm.expectEmit(); // emit Transfer(address(0), borrower.addr, loan.getId()); // vm.expectEmit(address(custodian));