diff --git a/.gas-snapshot b/.gas-snapshot index f79cea92..eda659a8 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,51 +1,50 @@ -DiffFuzzTestStarportLib:testSpentToReceived((uint8,address,uint256,uint256)[]) (runs: 256, μ: 880466, ~: 882693) -DiffFuzzTestStarportLib:testUnboundSpentToReceived((uint8,address,uint256,uint256)[]) (runs: 256, μ: 232918, ~: 237832) -IntegrationTestCaveats:testOriginateUnapprovedFulfiller() (gas: 341293) -IntegrationTestCaveats:testOriginateWBorrowerApproval() (gas: 298091) -IntegrationTestCaveats:testOriginateWCaveats() (gas: 272268) -IntegrationTestCaveats:testOriginateWCaveatsIncrementedNonce() (gas: 200258) -IntegrationTestCaveats:testOriginateWCaveatsInvalidSalt() (gas: 257879) -IntegrationTestCaveats:testOriginateWCaveatsInvalidSaltManual() (gas: 175824) -IntegrationTestCaveats:testOriginateWLenderApproval() (gas: 298188) -IntegrationTestCaveats:testRefinanceAsLender() (gas: 1036542) -IntegrationTestCaveats:testRefinanceCaveatFailure() (gas: 402664) -IntegrationTestCaveats:testRefinanceLoanStartAtBlockTimestampInvalidLoan() (gas: 377412) -IntegrationTestCaveats:testRefinanceUnapprovedFulfiller() (gas: 460158) -IntegrationTestCaveats:testRefinanceWCaveatsInvalidSalt() (gas: 381151) -IntegrationTestCaveats:testRefinanceWLenderApproval() (gas: 405713) +DiffFuzzTestStarportLib:testSpentToReceived((uint8,address,uint256,uint256)[]) (runs: 256, μ: 880557, ~: 883183) +DiffFuzzTestStarportLib:testUnboundSpentToReceived((uint8,address,uint256,uint256)[]) (runs: 256, μ: 232911, ~: 237832) +IntegrationTestCaveats:testOriginateUnapprovedFulfiller() (gas: 341166) +IntegrationTestCaveats:testOriginateWBorrowerApproval() (gas: 298037) +IntegrationTestCaveats:testOriginateWCaveats() (gas: 272104) +IntegrationTestCaveats:testOriginateWCaveatsIncrementedNonce() (gas: 200214) +IntegrationTestCaveats:testOriginateWCaveatsInvalidSalt() (gas: 257759) +IntegrationTestCaveats:testOriginateWCaveatsInvalidSaltManual() (gas: 175780) +IntegrationTestCaveats:testOriginateWLenderApproval() (gas: 298091) +IntegrationTestCaveats:testRefinanceAsLender() (gas: 1036148) +IntegrationTestCaveats:testRefinanceCaveatFailure() (gas: 402330) +IntegrationTestCaveats:testRefinanceLoanStartAtBlockTimestampInvalidLoan() (gas: 377358) +IntegrationTestCaveats:testRefinanceUnapprovedFulfiller() (gas: 459637) +IntegrationTestCaveats:testRefinanceWCaveatsInvalidSalt() (gas: 380750) +IntegrationTestCaveats:testRefinanceWLenderApproval() (gas: 405252) PausableNonReentrantImpl:test() (gas: 2442) PausableNonReentrantImpl:testReentrancy() (gas: 2735) -TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallBase() (gas: 1023396) -TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLender() (gas: 708447) -TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLiquidation() (gas: 747230) -TestAstariaV1Pricing:testGetRefiannceConsiderationValidEqualRate() (gas: 146499) -TestAstariaV1Pricing:testGetRefiannceConsiderationValidHigherRate() (gas: 158898) -TestAstariaV1Pricing:testGetRefiannceConsiderationValidLowerRate() (gas: 153927) +TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallBase() (gas: 1021149) +TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLender() (gas: 727571) +TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLiquidation() (gas: 1404896) +TestAstariaV1Pricing:testGetRefiannceConsiderationValidEqualRate() (gas: 146135) +TestAstariaV1Pricing:testGetRefiannceConsiderationValidHigherRate() (gas: 158343) +TestAstariaV1Pricing:testGetRefiannceConsiderationValidLowerRate() (gas: 153372) TestAstariaV1Pricing:testGetRefinanceConsiderationAsBorrowerZeroRate() (gas: 81159) -TestAstariaV1Pricing:testGetRefinanceConsiderationInsufficientRefinance() (gas: 108392) -TestAstariaV1Pricing:testGetRefinanceConsiderationInvalidRefinance() (gas: 88455) -TestAstariaV1Pricing:testGetRefinanceConsiderationZeroRate() (gas: 139117) -TestAstariaV1Settlement:testGetAuctionStart() (gas: 433653) -TestAstariaV1Settlement:testGetAuctionStartNotStarted() (gas: 433226) -TestAstariaV1Settlement:testGetCurrentAuctionPrice() (gas: 448508) -TestAstariaV1Settlement:testGetCurrentAuctionPriceNoAuction() (gas: 436857) -TestAstariaV1Settlement:testGetSettlementDutchAuctionSettlementAbove() (gas: 490478) -TestAstariaV1Settlement:testGetSettlementFailedDutchAuction() (gas: 448831) -TestAstariaV1Settlement:testGetSettlementLoanNotRecalled() (gas: 439333) -TestAstariaV1Settlement:testV1SettlementHandlerExecute() (gas: 419840) -TestAstariaV1Settlement:testV1SettlementHandlerValidate() (gas: 419952) -TestAstariaV1Settlement:testV1SettlementHandlerValidateInvalidHandler() (gas: 420076) -TestAstariaV1Status:testCannotRecallTwice() (gas: 580760) -TestAstariaV1Status:testCannotWithdrawLoanHasNotBeenRefinanced() (gas: 425689) -TestAstariaV1Status:testCannotWithdrawWithdrawDoesNotExist() (gas: 432118) -TestAstariaV1Status:testGenerateRecallConsideration() (gas: 481620) -TestAstariaV1Status:testInvalidRecallInvalidStakeType() (gas: 507923) -TestAstariaV1Status:testInvalidRecallLoanDoesNotExist() (gas: 523908) -TestAstariaV1Status:testIsActive() (gas: 432838) -TestAstariaV1Status:testIsRecalledInsideWindow() (gas: 571531) -TestAstariaV1Status:testIsRecalledOutsideWindow() (gas: 569432) -TestAstariaV1Status:testRecallRateActiveRecall() (gas: 557070) -TestAstariaV1Status:testRecallRateEmptyRecall() (gas: 430492) +TestAstariaV1Pricing:testGetRefinanceConsiderationInsufficientRefinance() (gas: 108010) +TestAstariaV1Pricing:testGetRefinanceConsiderationInvalidRefinance() (gas: 88264) +TestAstariaV1Pricing:testGetRefinanceConsiderationZeroRate() (gas: 138753) +TestAstariaV1Settlement:testGetAuctionStart() (gas: 433743) +TestAstariaV1Settlement:testGetAuctionStartNotStarted() (gas: 433316) +TestAstariaV1Settlement:testGetCurrentAuctionPrice() (gas: 448527) +TestAstariaV1Settlement:testGetCurrentAuctionPriceNoAuction() (gas: 436880) +TestAstariaV1Settlement:testGetSettlementDutchAuctionSettlementAbove() (gas: 490449) +TestAstariaV1Settlement:testGetSettlementFailedDutchAuction() (gas: 448917) +TestAstariaV1Settlement:testGetSettlementLoanNotRecalled() (gas: 439423) +TestAstariaV1Settlement:testV1SettlementHandlerValidate() (gas: 419993) +TestAstariaV1Settlement:testV1SettlementHandlerValidateInvalidHandler() (gas: 420117) +TestAstariaV1Status:testCannotRecallTwice() (gas: 580122) +TestAstariaV1Status:testCannotWithdrawLoanHasNotBeenRefinanced() (gas: 425694) +TestAstariaV1Status:testCannotWithdrawWithdrawDoesNotExist() (gas: 432123) +TestAstariaV1Status:testGenerateRecallConsideration() (gas: 481364) +TestAstariaV1Status:testInvalidRecallInvalidStakeType() (gas: 507391) +TestAstariaV1Status:testInvalidRecallLoanDoesNotExist() (gas: 523634) +TestAstariaV1Status:testIsActive() (gas: 432737) +TestAstariaV1Status:testIsRecalledInsideWindow() (gas: 570875) +TestAstariaV1Status:testIsRecalledOutsideWindow() (gas: 568776) +TestAstariaV1Status:testRecallRateActiveRecall() (gas: 556605) +TestAstariaV1Status:testRecallRateEmptyRecall() (gas: 430391) TestBorrowerEnforcer:testBERevertAdditionalTransfers() (gas: 73195) TestBorrowerEnforcer:testBERevertInvalidLoanTerms() (gas: 78316) TestBorrowerEnforcer:testBEValidLoanTerms() (gas: 69518) @@ -54,108 +53,111 @@ TestCompoundInterest:testAmountMax() (gas: 65767) TestCompoundInterest:testRateMax() (gas: 68106) TestCompoundInterest:testRateTooLowOne() (gas: 73157) TestCompoundInterest:testRateTooLowZero() (gas: 68419) -TestCustodian:testCannotLazyMintTwice() (gas: 76686) -TestCustodian:testCannotMintInvalidLoanInvalidCustodian() (gas: 66861) -TestCustodian:testCannotMintInvalidLoanValidCustodian() (gas: 72489) -TestCustodian:testCustodySelector() (gas: 2728398) -TestCustodian:testDefaultCustodySelectorRevert() (gas: 70083) -TestCustodian:testGenerateOrderInvalidHandlerExecution() (gas: 133050) -TestCustodian:testGenerateOrderRepay() (gas: 171937) -TestCustodian:testGenerateOrderRepayAsRepayApprovedBorrower() (gas: 197540) -TestCustodian:testGenerateOrderRepayERC1155AndERC20AndNative() (gas: 833734) -TestCustodian:testGenerateOrderRepayERC1155AndERC20AndNativeHandlerAuthorized() (gas: 757868) -TestCustodian:testGenerateOrderRepayERC1155WithRevert() (gas: 516688) -TestCustodian:testGenerateOrderRepayInvalidHookAddress() (gas: 90335) +TestCustodian:testCannotLazyMintTwice() (gas: 76753) +TestCustodian:testCannotMintInvalidLoanInvalidCustodian() (gas: 66884) +TestCustodian:testCannotMintInvalidLoanValidCustodian() (gas: 72556) +TestCustodian:testCustodySelector() (gas: 2820915) +TestCustodian:testDefaultCustodySelectorRevert() (gas: 70061) +TestCustodian:testGenerateOrderInvalidPostRepayment() (gas: 171281) +TestCustodian:testGenerateOrderInvalidPostSettlement() (gas: 155941) +TestCustodian:testGenerateOrderRepay() (gas: 175271) +TestCustodian:testGenerateOrderRepayAsRepayApprovedBorrower() (gas: 191405) +TestCustodian:testGenerateOrderRepayERC1155AndERC20AndNative() (gas: 827047) +TestCustodian:testGenerateOrderRepayERC1155AndERC20AndNativeHandlerAuthorized() (gas: 744382) +TestCustodian:testGenerateOrderRepayInvalidHookAddress() (gas: 90248) TestCustodian:testGenerateOrderRepayInvalidHookReturnType() (gas: 84652) -TestCustodian:testGenerateOrderRepayNotBorrower() (gas: 96426) -TestCustodian:testGenerateOrderSettlement() (gas: 146907) -TestCustodian:testGenerateOrderSettlementHandlerAuthorized() (gas: 155902) -TestCustodian:testGenerateOrderSettlementNoActiveLoan() (gas: 155924) -TestCustodian:testGenerateOrderSettlementUnauthorized() (gas: 94410) -TestCustodian:testGenerateOrdersWithLoanStartAtBlockTimestampInvalidLoan() (gas: 453017) -TestCustodian:testGetBorrower() (gas: 76234) -TestCustodian:testInvalidAction() (gas: 114498) +TestCustodian:testGenerateOrderRepayNotBorrower() (gas: 99148) +TestCustodian:testGenerateOrderSettlement() (gas: 147620) +TestCustodian:testGenerateOrderSettlementHandlerAuthorized() (gas: 153177) +TestCustodian:testGenerateOrderSettlementNoActiveLoan() (gas: 155828) +TestCustodian:testGenerateOrderSettlementUnauthorized() (gas: 94388) +TestCustodian:testGenerateOrdersWithLoanStartAtBlockTimestampInvalidLoan() (gas: 452795) +TestCustodian:testGetBorrower() (gas: 76322) +TestCustodian:testInvalidAction() (gas: 114520) TestCustodian:testInvalidActionRepayInActiveLoan() (gas: 117469) -TestCustodian:testInvalidActionSettleActiveLoan() (gas: 117407) -TestCustodian:testName() (gas: 7098) -TestCustodian:testNonPayableFunctions() (gas: 225792) -TestCustodian:testOnlySeaport() (gas: 17895) -TestCustodian:testPayableFunctions() (gas: 41667) -TestCustodian:testPreviewOrderNoActiveLoan() (gas: 98786) -TestCustodian:testPreviewOrderRepay() (gas: 227692) -TestCustodian:testPreviewOrderSettlement() (gas: 178524) -TestCustodian:testPreviewOrderSettlementInvalidFufliller() (gas: 100823) -TestCustodian:testPreviewOrderSettlementInvalidRepayer() (gas: 106856) -TestCustodian:testRatifyOrder() (gas: 178432) -TestCustodian:testSeaportMetadata() (gas: 8567) -TestCustodian:testSetRepayApproval() (gas: 37861) -TestCustodian:testSupportsInterface() (gas: 9450) +TestCustodian:testInvalidActionSettleActiveLoan() (gas: 117429) +TestCustodian:testMintWithApprovalSetAsBorrower() (gas: 356360) +TestCustodian:testMintWithApprovalSetAsBorrowerInvalidLoan() (gas: 58579) +TestCustodian:testMintWithApprovalSetNotAuthorized() (gas: 74561) +TestCustodian:testName() (gas: 7076) +TestCustodian:testNonPayableFunctions() (gas: 212635) +TestCustodian:testOnlySeaport() (gas: 17873) +TestCustodian:testPayableFunctions() (gas: 41645) +TestCustodian:testPreviewOrderNoActiveLoan() (gas: 98764) +TestCustodian:testPreviewOrderRepay() (gas: 228570) +TestCustodian:testPreviewOrderSettlement() (gas: 179304) +TestCustodian:testPreviewOrderSettlementInvalidFufliller() (gas: 100931) +TestCustodian:testPreviewOrderSettlementInvalidRepayer() (gas: 106834) +TestCustodian:testRatifyOrder() (gas: 181788) +TestCustodian:testSeaportMetadata() (gas: 8545) +TestCustodian:testSupportsInterface() (gas: 9428) TestCustodian:testSymbol() (gas: 7127) -TestCustodian:testTokenURI() (gas: 64817) +TestCustodian:testTokenURI() (gas: 64906) TestCustodian:testTokenURIInvalidLoan() (gas: 13218) TestLenderEnforcer:testLERevertAdditionalTransfersFromLender() (gas: 73743) TestLenderEnforcer:testLERevertInvalidLoanTerms() (gas: 78341) TestLenderEnforcer:testLEValidLoanTerms() (gas: 69496) TestLenderEnforcer:testLEValidLoanTermsAnyBorrower() (gas: 69494) TestLenderEnforcer:testLEValidLoanTermsWithAdditionalTransfers() (gas: 70740) -TestLoanCombinations:testLoan20For721SimpleInterestDutchFixedRepay() (gas: 537052) -TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 524681) -TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 554876) -TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 544618) -TestLoanCombinations:testLoanSimpleInterestEnglishFixed() (gas: 550094) -TestNewLoan:testBuyNowPayLater() (gas: 2832923) -TestNewLoan:testNewLoanERC721CollateralDefaultTerms2() (gas: 394541) +TestLoanCombinations:testLoan20For721SimpleInterestDutchFixedRepay() (gas: 542758) +TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 530387) +TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 560581) +TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 550323) +TestLoanCombinations:testLoanSimpleInterestEnglishFixed() (gas: 556101) +TestNewLoan:testBuyNowPayLater() (gas: 2832773) +TestNewLoan:testNewLoanERC721CollateralDefaultTerms2() (gas: 394391) TestNewLoan:testNewLoanERC721CollateralLessDebtThanOffered() (gas: 2348) TestNewLoan:testNewLoanRefinanceNew() (gas: 207) -TestNewLoan:testNewLoanViaOriginatorBorrowerApprovalAndLenderApproval() (gas: 305741) -TestNewLoan:testNewLoanViaOriginatorLenderApproval() (gas: 358465) -TestNewLoan:testSettleLoan() (gas: 608094) +TestNewLoan:testNewLoanViaOriginatorBorrowerApprovalAndLenderApproval() (gas: 305651) +TestNewLoan:testNewLoanViaOriginatorLenderApproval() (gas: 358345) +TestNewLoan:testSettleLoan() (gas: 611290) TestPausableNonReentrant:testNotOwner() (gas: 21254) TestPausableNonReentrant:testPauseAndUnpause() (gas: 22555) TestPausableNonReentrant:testReentrancy() (gas: 15360) TestPausableNonReentrant:testUnpauseWhenNotPaused() (gas: 12582) TestRefStarportLib:testSpentToReceived() (gas: 13315) TestRefStarportLib:testValidateSalt(address,bytes32) (runs: 256, μ: 33865, ~: 33865) -TestRepayLoan:testRepayLoanApprovedRepayer() (gas: 629500) -TestRepayLoan:testRepayLoanBase() (gas: 565794) -TestRepayLoan:testRepayLoanGenerateOrderNotSeaport() (gas: 402462) -TestRepayLoan:testRepayLoanInSettlement() (gas: 550078) -TestRepayLoan:testRepayLoanInvalidRepayer() (gas: 564487) -TestRepayLoan:testRepayLoanThatDoesNotExist() (gas: 837152) +TestRepayLoan:testRepayLoanApprovedRepayer() (gas: 635212) +TestRepayLoan:testRepayLoanBase() (gas: 571502) +TestRepayLoan:testRepayLoanGenerateOrderNotSeaport() (gas: 402312) +TestRepayLoan:testRepayLoanInSettlement() (gas: 549952) +TestRepayLoan:testRepayLoanInvalidRepayer() (gas: 569739) +TestRepayLoan:testRepayLoanThatDoesNotExist() (gas: 842802) TestSimpleInterestPricing:test_calculateInterest() (gas: 800891) TestSimpleInterestPricing:test_getPaymentConsideration() (gas: 882219) TestSimpleInterestPricing:test_getRefinanceConsideration() (gas: 876412) -TestStarport:testActive() (gas: 67100) -TestStarport:testAdditionalTransfers() (gas: 295920) -TestStarport:testCannotIssueSameLoanTwice() (gas: 336999) +TestStarport:testActive() (gas: 67122) +TestStarport:testAdditionalTransfers() (gas: 295800) +TestStarport:testApplyRefinanceConsiderationToLoanMalformed() (gas: 76450) +TestStarport:testCannotIssueSameLoanTwice() (gas: 336811) TestStarport:testCannotOriginateWhilePaused() (gas: 70790) -TestStarport:testCannotSettleInvalidLoan() (gas: 72725) -TestStarport:testCannotSettleUnlessValidCustodian() (gas: 68816) -TestStarport:testCaveatEnforcerRevert() (gas: 123993) -TestStarport:testDefaultFeeRake() (gas: 355025) -TestStarport:testExoticDebtWithNoCaveatsNotAsBorrower() (gas: 371268) -TestStarport:testIncrementCaveatNonce() (gas: 34671) -TestStarport:testInitializedFlagSetProperly() (gas: 65260) -TestStarport:testInvalidAmountCollateral() (gas: 157842) -TestStarport:testInvalidAmountCollateral721() (gas: 157819) -TestStarport:testInvalidItemType() (gas: 143741) -TestStarport:testInvalidTransferLengthCollateral() (gas: 165898) -TestStarport:testInvalidTransferLengthDebt() (gas: 170468) -TestStarport:testInvalidateCaveatSalt() (gas: 32830) +TestStarport:testCannotSettleInvalidLoan() (gas: 72723) +TestStarport:testCannotSettleUnlessValidCustodian() (gas: 68866) +TestStarport:testCaveatEnforcerRevert() (gas: 124015) +TestStarport:testDefaultFeeRake() (gas: 354905) +TestStarport:testExoticDebtWithNoCaveatsNotAsBorrower() (gas: 371048) +TestStarport:testIncrementCaveatNonce() (gas: 34604) +TestStarport:testInitializedFlagSetProperly() (gas: 65282) +TestStarport:testInvalidAmountCollateral() (gas: 157834) +TestStarport:testInvalidAmountCollateral721() (gas: 157811) +TestStarport:testInvalidItemType() (gas: 143733) +TestStarport:testInvalidTransferLengthCollateral() (gas: 165890) +TestStarport:testInvalidTransferLengthDebt() (gas: 170460) +TestStarport:testInvalidateCaveatSalt() (gas: 32852) TestStarport:testName() (gas: 7216) -TestStarport:testNonDefaultCustodianCustodyCallFails() (gas: 195151) -TestStarport:testNonDefaultCustodianCustodyCallSuccess() (gas: 261025) +TestStarport:testNonDefaultCustodianCustodyCallFails() (gas: 195113) +TestStarport:testNonDefaultCustodianCustodyCallSuccess() (gas: 260897) TestStarport:testNonPayableFunctions() (gas: 180435) -TestStarport:testOverrideFeeRake() (gas: 348758) -TestStarport:testPause() (gas: 17186) -TestStarport:testSupportsInterface() (gas: 9181) -TestStarport:testSymbol() (gas: 7257) -TestStarport:testTokenNoCodeCollateral() (gas: 142510) -TestStarport:testTokenNoCodeDebt() (gas: 175616) -TestStarport:testTokenURI() (gas: 65021) -TestStarport:testTokenURIInvalidLoan() (gas: 13394) -TestStarport:testTransferFromFail() (gas: 80066) -TestStarport:testUnpause() (gas: 16309) +TestStarport:testOverrideFeeRake() (gas: 348638) +TestStarport:testPause() (gas: 17119) +TestStarport:testSupportsInterface() (gas: 9203) +TestStarport:testSymbol() (gas: 7149) +TestStarport:testTokenNoCodeCollateral() (gas: 142480) +TestStarport:testTokenNoCodeDebt() (gas: 175608) +TestStarport:testTokenURI() (gas: 64928) +TestStarport:testTokenURIInvalidLoan() (gas: 13307) +TestStarport:testTransferFromFail() (gas: 80172) +TestStarport:testUnpause() (gas: 16331) TestStarportLib:testSpentToReceived() (gas: 13315) TestStarportLib:testValidateSalt(address,bytes32) (runs: 256, μ: 33865, ~: 33865) TestStrategistOriginator:testEncodeWithAccountCounter() (gas: 12307) @@ -169,6 +171,6 @@ TestStrategistOriginator:testInvalidDebtAmountAskingMoreThanOffered() (gas: 2085 TestStrategistOriginator:testInvalidDebtAmountOfferingZero() (gas: 188880) TestStrategistOriginator:testInvalidDebtAmountRequestingZero() (gas: 208756) TestStrategistOriginator:testInvalidDebtLength() (gas: 207383) -TestStrategistOriginator:testInvalidOffer() (gas: 400847) +TestStrategistOriginator:testInvalidOffer() (gas: 400727) TestStrategistOriginator:testInvalidSigner() (gas: 210594) TestStrategistOriginator:testSetStrategist() (gas: 17818) \ No newline at end of file diff --git a/.github/workflows/lint_test.yml b/.github/workflows/lint_test.yml index 6303ef52..25b3fe1c 100644 --- a/.github/workflows/lint_test.yml +++ b/.github/workflows/lint_test.yml @@ -32,7 +32,7 @@ jobs: run: forge test -vvv - name: Snapshot - run: forge snapshot --check + run: forge snapshot --check --no-match-path '*fuzz*' diff --git a/src/Custodian.sol b/src/Custodian.sol index 648758de..99f49a04 100644 --- a/src/Custodian.sol +++ b/src/Custodian.sol @@ -49,9 +49,11 @@ contract Custodian is ERC721, ContractOffererInterface { error ImplementInChild(); error InvalidAction(); error InvalidFulfiller(); - error InvalidHandlerExecution(); + error InvalidPostSettlement(); + error InvalidPostRepayment(); error InvalidLoan(); error InvalidRepayer(); + error NotAuthorized(); error NotSeaport(); error NotEnteredViaSeaport(); error NotStarport(); @@ -154,16 +156,24 @@ contract Custodian is ERC721, ContractOffererInterface { _safeMint(loan.borrower, loanId, encodedLoan); } - /** - * @dev Set's approvals for who can repay a loan on behalf of the borrower. + * @dev Mints a custody token for a loan. * - * @param who The address of the account to modify approval for - * @param approved The approval status + * @param loan The loan to mint a custody token for + * @param approvedTo The address with pre approvals set */ - function setRepayApproval(address who, bool approved) external { - repayApproval[msg.sender][who] = approved; - emit RepayApproval(msg.sender, who, approved); + + function mintWithApprovalSet(Starport.Loan calldata loan, address approvedTo) external { + bytes memory encodedLoan = abi.encode(loan); + uint256 loanId = uint256(keccak256(encodedLoan)); + if (loan.custodian != address(this) || !SP.active(loanId)) { + revert InvalidLoan(); + } + if (msg.sender != loan.borrower) { + revert NotAuthorized(); + } + _safeMint(loan.borrower, loanId, encodedLoan); + _approve(loan.borrower, approvedTo, loanId); } /** @@ -208,7 +218,7 @@ contract Custodian is ERC721, ContractOffererInterface { } if (action == Actions.Repayment && Status(loan.terms.status).isActive(loan)) { address borrower = getBorrower(loan); - if (fulfiller != borrower && !repayApproval[borrower][fulfiller]) { + if (fulfiller != borrower && fulfiller != _getApproved(loan.getId())) { revert InvalidRepayer(); } @@ -222,6 +232,7 @@ contract Custodian is ERC721, ContractOffererInterface { consideration = StarportLib.mergeSpentItemsToReceivedItems(payment, loan.issuer, carry, loan.originator); _settleLoan(loan); + _postRepaymentExecute(loan, fulfiller); } else if (action == Actions.Settlement && !Status(loan.terms.status).isActive(loan)) { address authorized; //add in originator fee @@ -236,18 +247,11 @@ contract Custodian is ERC721, ContractOffererInterface { _setOfferApprovalsWithSeaport(offer); } else if (authorized == loan.terms.settlement || authorized == loan.issuer) { _moveCollateralToAuthorized(loan.collateral, authorized); - _beforeSettlementHandlerHook(loan); - if ( - authorized == loan.terms.settlement - && Settlement(loan.terms.settlement).execute(loan, fulfiller) != Settlement.execute.selector - ) { - revert InvalidHandlerExecution(); - } - _afterSettlementHandlerHook(loan); } else { revert InvalidFulfiller(); } _settleLoan(loan); + _postSettlementExecute(loan, fulfiller); } else { revert InvalidAction(); } @@ -400,6 +404,40 @@ contract Custodian is ERC721, ContractOffererInterface { } } + /** + * @dev settle the loan with the LoanManager + * + * @param loan The the loan that is settled + * @param fulfiller The address executing seaport + */ + function _postSettlementExecute(Starport.Loan memory loan, address fulfiller) internal virtual { + _beforeSettlementHandlerHook(loan); + if ( + Settlement(loan.terms.settlement).postSettlement{gas: 100_000}(loan, fulfiller) + != Settlement.postSettlement.selector + ) { + revert InvalidPostSettlement(); + } + _afterSettlementHandlerHook(loan); + } + /** + * @dev settle the loan with the LoanManager + * + * @param loan The the loan that is settled + * @param fulfiller The address executing seaport + */ + + function _postRepaymentExecute(Starport.Loan memory loan, address fulfiller) internal virtual { + _beforeSettlementHandlerHook(loan); + if ( + Settlement(loan.terms.settlement).postRepayment{gas: 100_000}(loan, fulfiller) + != Settlement.postRepayment.selector + ) { + revert InvalidPostRepayment(); + } + _afterSettlementHandlerHook(loan); + } + /** * @dev settle the loan with the LoanManager * diff --git a/src/Starport.sol b/src/Starport.sol index 23cc748e..681303f6 100644 --- a/src/Starport.sol +++ b/src/Starport.sol @@ -37,10 +37,6 @@ import {Ownable} from "solady/src/auth/Ownable.sol"; import {SafeTransferLib} from "solady/src/utils/SafeTransferLib.sol"; import {PausableNonReentrant} from "starport-core/lib/PausableNonReentrant.sol"; -interface LoanSettledCallback { - function onLoanSettled(Starport.Loan calldata loan) external; -} - contract Starport is ERC721, PausableNonReentrant { using FixedPointMathLib for uint256; @@ -473,10 +469,6 @@ contract Starport is ERC721, PausableNonReentrant { _burn(tokenId); } _setExtraData(tokenId, uint8(FieldFlags.INACTIVE)); - - if (loan.issuer.code.length > 0) { - loan.issuer.call(abi.encodeWithSelector(LoanSettledCallback.onLoanSettled.selector, loan)); - } emit Close(tokenId); } diff --git a/src/settlement/AstariaV1Settlement.sol b/src/settlement/AstariaV1Settlement.sol index e3b59107..f0387af6 100644 --- a/src/settlement/AstariaV1Settlement.sol +++ b/src/settlement/AstariaV1Settlement.sol @@ -6,7 +6,6 @@ import {BaseRecall} from "starport-core/status/BaseRecall.sol"; import {DutchAuctionSettlement} from "starport-core/settlement/DutchAuctionSettlement.sol"; import {StarportLib} from "starport-core/lib/StarportLib.sol"; import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; - import {Pricing} from "starport-core/pricing/Pricing.sol"; import {BasePricing} from "starport-core/pricing/BasePricing.sol"; @@ -145,8 +144,19 @@ contract AstariaV1Settlement is DutchAuctionSettlement { } } - function execute(Starport.Loan calldata loan, address fulfiller) external virtual override returns (bytes4) { - revert ExecuteHandlerNotImplemented(); + function postSettlement(Starport.Loan calldata loan, address fulfiller) + external + virtual + override + returns (bytes4) + { + // TODO: do we need the commented out code if we dont care about reverts anyways, seems like extra gas + // (address recaller, uint64 recallStart) = BaseRecall(loan.terms.status).recalls(loan.getId()); + // if (recallStart != 0 || recaller != address(0)) { + //we dont wanna revert if theres ever a halt in the underlying call, settlement must complete + loan.terms.status.call(abi.encodeWithSelector(BaseRecall.withdraw.selector, loan, fulfiller)); + // } + return Settlement.postSettlement.selector; } function validate(Starport.Loan calldata loan) external view virtual override returns (bool) { diff --git a/src/settlement/DutchAuctionSettlement.sol b/src/settlement/DutchAuctionSettlement.sol index 7e7ecbe7..4a31e126 100644 --- a/src/settlement/DutchAuctionSettlement.sol +++ b/src/settlement/DutchAuctionSettlement.sol @@ -30,8 +30,17 @@ abstract contract DutchAuctionSettlement is Settlement, AmountDeriver { uint256 window; } - function execute(Starport.Loan calldata loan, address fulfiller) external virtual override returns (bytes4) { - return Settlement.execute.selector; + function postSettlement(Starport.Loan calldata loan, address fulfiller) + external + virtual + override + returns (bytes4) + { + return Settlement.postSettlement.selector; + } + + function postRepayment(Starport.Loan calldata loan, address fulfiller) external virtual override returns (bytes4) { + return Settlement.postRepayment.selector; } function getAuctionStart(Starport.Loan calldata loan) public view virtual returns (uint256); diff --git a/src/settlement/EnglishAuctionSettlement.sol b/src/settlement/EnglishAuctionSettlement.sol index df7806b7..9ca812df 100644 --- a/src/settlement/EnglishAuctionSettlement.sol +++ b/src/settlement/EnglishAuctionSettlement.sol @@ -25,6 +25,7 @@ import { OrderType } from "seaport-types/src/lib/ConsiderationStructs.sol"; import {Pricing} from "starport-core/pricing/Pricing.sol"; +import {Status} from "starport-core/status/Status.sol"; contract EnglishAuctionSettlement is Settlement { using FixedPointMathLib for uint256; @@ -55,11 +56,20 @@ contract EnglishAuctionSettlement is Settlement { return details.reservePrice.length == loan.debt.length; } - function execute(Starport.Loan calldata loan, address fulfiller) external virtual override returns (bytes4) { + function postSettlement(Starport.Loan calldata loan, address fulfiller) + external + virtual + override + returns (bytes4) + { if (fulfiller != address(this)) { revert("must liquidate via the handler to trigger english auction"); } - return Settlement.execute.selector; + return Settlement.postSettlement.selector; + } + + function postRepayment(Starport.Loan calldata loan, address fulfiller) external virtual override returns (bytes4) { + return Settlement.postRepayment.selector; } function getSettlement(Starport.Loan calldata loan) diff --git a/src/settlement/FixedTermDutchAuctionSettlement.sol b/src/settlement/FixedTermDutchAuctionSettlement.sol index 6d33a7ee..4e930a19 100644 --- a/src/settlement/FixedTermDutchAuctionSettlement.sol +++ b/src/settlement/FixedTermDutchAuctionSettlement.sol @@ -18,8 +18,13 @@ contract FixedTermDutchAuctionSettlement is DutchAuctionSettlement { return loan.start + details.loanDuration; } - function execute(Starport.Loan calldata loan, address fulfiller) external virtual override returns (bytes4) { - return Settlement.execute.selector; + function postSettlement(Starport.Loan calldata loan, address fulfiller) + external + virtual + override + returns (bytes4) + { + return Settlement.postSettlement.selector; } function validate(Starport.Loan calldata loan) external view virtual override returns (bool) { diff --git a/src/settlement/Settlement.sol b/src/settlement/Settlement.sol index abe59624..81d336f1 100644 --- a/src/settlement/Settlement.sol +++ b/src/settlement/Settlement.sol @@ -32,7 +32,9 @@ abstract contract Settlement is TokenReceiverInterface { SP = SP_; } - function execute(Starport.Loan calldata loan, address fulfiller) external virtual returns (bytes4); + function postSettlement(Starport.Loan calldata loan, address fulfiller) external virtual returns (bytes4); + + function postRepayment(Starport.Loan calldata loan, address fulfiller) external virtual returns (bytes4); function validate(Starport.Loan calldata loan) external view virtual returns (bool); diff --git a/src/status/BaseRecall.sol b/src/status/BaseRecall.sol index d9cdc75d..7261cd91 100644 --- a/src/status/BaseRecall.sol +++ b/src/status/BaseRecall.sol @@ -117,7 +117,7 @@ abstract contract BaseRecall { } // transfers all stake to anyone who asks after the LM token is burned - function withdraw(Starport.Loan calldata loan, address payable receiver) external { + function withdraw(Starport.Loan calldata loan, address receiver) external { Details memory details = abi.decode(loan.terms.statusData, (Details)); bytes memory encodedLoan = abi.encode(loan); uint256 loanId = uint256(keccak256(encodedLoan)); @@ -171,12 +171,11 @@ abstract contract BaseRecall { } } - function generateRecallConsideration( - Starport.Loan calldata loan, - uint256 proportion, - address from, - address payable to - ) external view returns (AdditionalTransfer[] memory consideration) { + function generateRecallConsideration(Starport.Loan calldata loan, uint256 proportion, address from, address to) + external + view + returns (AdditionalTransfer[] memory consideration) + { Details memory details = abi.decode(loan.terms.statusData, (Details)); return _generateRecallConsideration(loan, 0, details.recallStakeDuration, proportion, from, to); } @@ -187,7 +186,7 @@ abstract contract BaseRecall { uint256 end, uint256 proportion, address from, - address payable to + address to ) internal view returns (AdditionalTransfer[] memory additionalTransfers) { uint256[] memory stake = _getRecallStake(loan, start, end); additionalTransfers = new AdditionalTransfer[](stake.length); diff --git a/test/AstariaV1Test.sol b/test/AstariaV1Test.sol index b2e9a6e9..61b0b4fe 100644 --- a/test/AstariaV1Test.sol +++ b/test/AstariaV1Test.sol @@ -29,12 +29,12 @@ contract AstariaV1Test is StarportTest { pricing = new AstariaV1Pricing(SP); settlement = new AstariaV1Settlement(SP); - hook = new AstariaV1Status(SP); + status = new AstariaV1Status(SP); lenderEnforcer = new AstariaV1LenderEnforcer(); vm.startPrank(recaller.addr); - erc20s[0].approve(address(hook), 1e18); + erc20s[0].approve(address(status), 1e18); vm.stopPrank(); // // 1% interest rate per second diff --git a/test/StarportTest.sol b/test/StarportTest.sol index edfa5df9..5749648d 100644 --- a/test/StarportTest.sol +++ b/test/StarportTest.sol @@ -61,7 +61,6 @@ import {ERC721} from "solady/src/tokens/ERC721.sol"; import {ERC1155} from "solady/src/tokens/ERC1155.sol"; import {ContractOffererInterface} from "seaport-types/src/interfaces/ContractOffererInterface.sol"; import {TokenReceiverInterface} from "starport-core/interfaces/TokenReceiverInterface.sol"; -import {LoanSettledCallback} from "starport-core/Starport.sol"; import {Actions} from "starport-core/lib/StarportLib.sol"; import {CaveatEnforcer} from "starport-core/enforcers/CaveatEnforcer.sol"; @@ -77,9 +76,7 @@ interface IWETH9 { function withdraw(uint256) external; } -contract MockIssuer is LoanSettledCallback, TokenReceiverInterface { - function onLoanSettled(Starport.Loan memory loan) external {} - +contract MockIssuer is TokenReceiverInterface { function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external override @@ -128,7 +125,7 @@ contract StarportTest is BaseOrderTest { Pricing pricing; Settlement settlement; - Status hook; + Status status; uint256 defaultLoanDuration = 14 days; @@ -205,7 +202,7 @@ contract StarportTest is BaseOrderTest { SO = new StrategistOriginator(SP, strategist.addr, 1e16, address(this)); pricing = new SimpleInterestPricing(SP); settlement = new FixedTermDutchAuctionSettlement(SP); - hook = new FixedTermStatus(); + status = new FixedTermStatus(); vm.label(address(erc721s[0]), "Collateral NFT"); vm.label(address(erc721s[1]), "Collateral2 NFT"); vm.label(address(erc20s[0]), "Debt ERC20"); @@ -484,7 +481,7 @@ contract StarportTest is BaseOrderTest { collateral: newCollateral, debt: newDebt, terms: Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, diff --git a/test/integration-testing/TestAstariaV1Loan.sol b/test/integration-testing/TestAstariaV1Loan.sol index 2734f4c0..90b4c217 100644 --- a/test/integration-testing/TestAstariaV1Loan.sol +++ b/test/integration-testing/TestAstariaV1Loan.sol @@ -11,10 +11,13 @@ import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; contract TestAstariaV1Loan is AstariaV1Test { using FixedPointMathLib for uint256; using {StarportLib.getId} for Starport.Loan; + using Cast for *; + + Starport.Loan activeLoan; function testNewLoanERC721CollateralDefaultTermsRecallBase() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -29,7 +32,7 @@ contract TestAstariaV1Loan is AstariaV1Test { vm.startPrank(recaller.addr); vm.expectRevert(BaseRecall.RecallBeforeHoneymoonExpiry.selector); // attempt recall before honeymoon period has ended - BaseRecall(address(hook)).recall(loan); + BaseRecall(address(status)).recall(loan); vm.stopPrank(); } { @@ -59,17 +62,17 @@ contract TestAstariaV1Loan is AstariaV1Test { uint256 stake; { uint256 balanceBefore = erc20s[0].balanceOf(recaller.addr); - uint256 recallContractBalanceBefore = erc20s[0].balanceOf(address(hook)); + uint256 recallContractBalanceBefore = erc20s[0].balanceOf(address(status)); BaseRecall.Details memory details = abi.decode(loan.terms.statusData, (BaseRecall.Details)); vm.warp(block.timestamp + details.honeymoon); vm.startPrank(recaller.addr); - BaseRecall recallContract = BaseRecall(address(hook)); + BaseRecall recallContract = BaseRecall(address(status)); recallContract.recall(loan); vm.stopPrank(); uint256 balanceAfter = erc20s[0].balanceOf(recaller.addr); - uint256 recallContractBalanceAfter = erc20s[0].balanceOf(address(hook)); + uint256 recallContractBalanceAfter = erc20s[0].balanceOf(address(status)); BasePricing.Details memory pricingDetails = abi.decode(loan.terms.pricingData, (BasePricing.Details)); stake = BasePricing(address(pricing)).calculateInterest( @@ -84,7 +87,7 @@ contract TestAstariaV1Loan is AstariaV1Test { } { uint256 loanId = loan.getId(); - BaseRecall recallContract = BaseRecall(address(hook)); + BaseRecall recallContract = BaseRecall(address(status)); address recallerAddr; uint64 start; (recallerAddr, start) = recallContract.recalls(loanId); @@ -93,7 +96,7 @@ contract TestAstariaV1Loan is AstariaV1Test { assertEq(start, block.timestamp, "Recall start logged incorrectly"); } { - BaseRecall recallContract = BaseRecall(address(hook)); + BaseRecall recallContract = BaseRecall(address(status)); vm.expectRevert(BaseRecall.LoanHasNotBeenRefinanced.selector); // attempt a withdraw without the loan being refinanced recallContract.withdraw(loan, payable(address(this))); @@ -203,13 +206,13 @@ contract TestAstariaV1Loan is AstariaV1Test { } { uint256 withdrawerBalanceBefore = erc20s[0].balanceOf(address(this)); - uint256 recallContractBalanceBefore = erc20s[0].balanceOf(address(hook)); - BaseRecall recallContract = BaseRecall(address(hook)); + uint256 recallContractBalanceBefore = erc20s[0].balanceOf(address(status)); + BaseRecall recallContract = BaseRecall(address(status)); // attempt a withdraw after the loan has been successfully refinanced recallContract.withdraw(loan, payable(address(this))); uint256 withdrawerBalanceAfter = erc20s[0].balanceOf(address(this)); - uint256 recallContractBalanceAfter = erc20s[0].balanceOf(address(hook)); + uint256 recallContractBalanceAfter = erc20s[0].balanceOf(address(status)); assertEq( withdrawerBalanceBefore + stake, withdrawerBalanceAfter, "Withdrawer did not recover stake as expected" ); @@ -224,7 +227,7 @@ contract TestAstariaV1Loan is AstariaV1Test { // lender is recaller, liquidation amount is 0 function testNewLoanERC721CollateralDefaultTermsRecallLender() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -238,18 +241,18 @@ contract TestAstariaV1Loan is AstariaV1Test { uint256 stake; { uint256 balanceBefore = erc20s[0].balanceOf(lender.addr); - uint256 recallContractBalanceBefore = erc20s[0].balanceOf(address(hook)); + uint256 recallContractBalanceBefore = erc20s[0].balanceOf(address(status)); BaseRecall.Details memory details = abi.decode(loan.terms.statusData, (BaseRecall.Details)); vm.warp(block.timestamp + details.honeymoon); vm.startPrank(lender.addr); - conduitController.updateChannel(lenderConduit, address(hook), true); - BaseRecall recallContract = BaseRecall(address(hook)); + conduitController.updateChannel(lenderConduit, address(status), true); + BaseRecall recallContract = BaseRecall(address(status)); erc20s[0].approve(loan.terms.status, 10e18); recallContract.recall(loan); vm.stopPrank(); uint256 balanceAfter = erc20s[0].balanceOf(lender.addr); - uint256 recallContractBalanceAfter = erc20s[0].balanceOf(address(hook)); + uint256 recallContractBalanceAfter = erc20s[0].balanceOf(address(status)); BasePricing.Details memory pricingDetails = abi.decode(loan.terms.pricingData, (BasePricing.Details)); stake = BasePricing(address(pricing)).calculateInterest( @@ -336,7 +339,7 @@ contract TestAstariaV1Loan is AstariaV1Test { // recaller is not the lender, liquidation amount is a dutch auction function testNewLoanERC721CollateralDefaultTermsRecallLiquidation() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -347,22 +350,23 @@ contract TestAstariaV1Loan is AstariaV1Test { _createLoan721Collateral20Debt({lender: lender.addr, borrowAmount: 1e18, terms: terms}); uint256 loanId = loan.getId(); + loan.toStorage(activeLoan); uint256 elapsedTime; uint256 stake; { uint256 balanceBefore = erc20s[0].balanceOf(recaller.addr); - uint256 recallContractBalanceBefore = erc20s[0].balanceOf(address(hook)); + uint256 recallContractBalanceBefore = erc20s[0].balanceOf(address(status)); BaseRecall.Details memory details = abi.decode(loan.terms.statusData, (BaseRecall.Details)); vm.warp(block.timestamp + details.honeymoon); elapsedTime += details.honeymoon; vm.startPrank(recaller.addr); - BaseRecall recallContract = BaseRecall(address(hook)); + BaseRecall recallContract = BaseRecall(address(status)); recallContract.recall(loan); vm.stopPrank(); uint256 balanceAfter = erc20s[0].balanceOf(recaller.addr); - uint256 recallContractBalanceAfter = erc20s[0].balanceOf(address(hook)); + uint256 recallContractBalanceAfter = erc20s[0].balanceOf(address(status)); BasePricing.Details memory pricingDetails = abi.decode(loan.terms.pricingData, (BasePricing.Details)); stake = BasePricing(address(pricing)).calculateInterest( @@ -406,6 +410,7 @@ contract TestAstariaV1Loan is AstariaV1Test { "Settlement consideration length for a dutch auction should be 3 (carry, recaller, and the lender)" ); assertEq(restricted, address(0), "SettlementConsideration should be unrestricted"); + AdditionalTransfer[] memory extraPayment; { BasePricing.Details memory pricingDetails = abi.decode(loan.terms.pricingData, (BasePricing.Details)); uint256 interest = @@ -422,6 +427,9 @@ contract TestAstariaV1Loan is AstariaV1Test { settlementPrice - recallerReward, "Settlement consideration for lender incorrect" ); + extraPayment = AstariaV1Status(activeLoan.terms.status).generateRecallConsideration( + activeLoan, 1e18, activeLoan.terms.status, address(this) + ); } ConsiderationItem[] memory consider = new ConsiderationItem[]( settlementConsideration.length @@ -446,7 +454,7 @@ contract TestAstariaV1Loan is AstariaV1Test { numerator: 1, denominator: 1, parameters: op, - extraData: abi.encode(Actions.Settlement, loan), + extraData: abi.encode(Actions.Settlement, activeLoan), signature: "" }); @@ -458,7 +466,11 @@ contract TestAstariaV1Loan is AstariaV1Test { }); uint256 balanceAfter = erc20s[0].balanceOf(address(this)); address owner = erc721s[0].ownerOf(1); - assertEq(balanceBefore - 500 ether, balanceAfter, "balance of buyer not decremented correctly"); + assertEq( + balanceBefore - 500 ether + extraPayment[0].amount, + balanceAfter, + "balance of buyer not decremented correctly" + ); assertEq(owner, address(this), "Test address should be the owner of the NFT after settlement"); } } diff --git a/test/integration-testing/TestNewLoan.sol b/test/integration-testing/TestNewLoan.sol index 7ff29dd9..0c31f4c4 100644 --- a/test/integration-testing/TestNewLoan.sol +++ b/test/integration-testing/TestNewLoan.sol @@ -57,7 +57,7 @@ contract TestNewLoan is StarportTest { Custodian custody = Custodian(SP.defaultCustodian()); Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, diff --git a/test/integration-testing/TestRepayLoan.sol b/test/integration-testing/TestRepayLoan.sol index 7cfe4021..a9450a5d 100644 --- a/test/integration-testing/TestRepayLoan.sol +++ b/test/integration-testing/TestRepayLoan.sol @@ -13,7 +13,7 @@ contract TestRepayLoan is StarportTest { function testRepayLoanBase() public { uint256 borrowAmount = 1e18; Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -37,7 +37,7 @@ contract TestRepayLoan is StarportTest { function testRepayLoanInvalidRepayer() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -105,7 +105,7 @@ contract TestRepayLoan is StarportTest { function testRepayLoanApprovedRepayer() public { uint256 borrowAmount = 1e18; Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -122,7 +122,7 @@ contract TestRepayLoan is StarportTest { uint256 interest = SimpleInterestPricing(loan.terms.pricing).calculateInterest(10 days, loan.debt[0].amount, details.rate); erc20s[0].approve(address(SP.seaport()), loan.debt[0].amount + interest); - custodian.setRepayApproval(address(this), true); + custodian.mintWithApprovalSet(loan, address(this)); vm.stopPrank(); _repayLoan(loan, address(this)); @@ -131,7 +131,7 @@ contract TestRepayLoan is StarportTest { // calling generateOrder on the Custodian to test the onlySeaport modifier function testRepayLoanGenerateOrderNotSeaport() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -155,7 +155,7 @@ contract TestRepayLoan is StarportTest { function testRepayLoanInSettlement() public { uint256 borrowAmount = 1e18; Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -220,7 +220,7 @@ contract TestRepayLoan is StarportTest { function testRepayLoanThatDoesNotExist() public { uint256 borrowAmount = 1e18; Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, diff --git a/test/unit-testing/TestCustodian.sol b/test/unit-testing/TestCustodian.sol index 2ce625b2..90edc1d7 100644 --- a/test/unit-testing/TestCustodian.sol +++ b/test/unit-testing/TestCustodian.sol @@ -70,10 +70,6 @@ contract TestCustodian is StarportTest, DeepEq, MockCall { vm.expectRevert(); payable(address(custodian)).call{value: 1 ether}(abi.encodeWithSelector(Custodian.mint.selector, activeLoan)); vm.expectRevert(); - payable(address(custodian)).call{value: 1 ether}( - abi.encodeWithSelector(Custodian.setRepayApproval.selector, address(0), false) - ); - vm.expectRevert(); payable(address(custodian)).call{value: 1 ether}( abi.encodeWithSelector( Custodian.ratifyOrder.selector, @@ -130,11 +126,37 @@ contract TestCustodian is StarportTest, DeepEq, MockCall { custodian.tokenURI(uint256(0)); } - function testSetRepayApproval() public { - vm.expectEmit(true, false, false, false); - emit RepayApproval(address(this), borrower.addr, true); - Custodian(custodian).setRepayApproval(borrower.addr, true); - assert(Custodian(custodian).repayApproval(address(this), borrower.addr)); + event Approval(address owner, address account, uint256 id); + + function testMintWithApprovalSetAsBorrower() public { + Starport.Loan memory loan = generateDefaultLoanTerms(); + loan.collateral[0].identifier = uint256(3); + 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)); + // emit Approval(loan.borrower, address(this), loan.getId()); + vm.prank(borrower.addr); + Custodian(custodian).mintWithApprovalSet(loan, address(this)); + assert(Custodian(custodian).getApproved(loan.getId()) == address(this)); + } + + function testMintWithApprovalSetAsBorrowerInvalidLoan() public { + Starport.Loan memory loan = generateDefaultLoanTerms(); + loan.collateral[0].identifier = uint256(3); + loan.start = block.timestamp; + loan.originator = borrower.addr; + loan.custodian = address(this); + vm.expectRevert(abi.encodeWithSelector(Custodian.InvalidLoan.selector)); + vm.prank(borrower.addr); + Custodian(custodian).mintWithApprovalSet(loan, address(this)); + } + + function testMintWithApprovalSetNotAuthorized() public { + vm.expectRevert(abi.encodeWithSelector(Custodian.NotAuthorized.selector)); + Custodian(custodian).mintWithApprovalSet(activeLoan, address(this)); } function testCannotMintInvalidLoanValidCustodian() public { @@ -211,38 +233,12 @@ contract TestCustodian is StarportTest, DeepEq, MockCall { function testGenerateOrderRepayAsRepayApprovedBorrower() public { vm.prank(activeLoan.borrower); - custodian.setRepayApproval(address(this), true); + custodian.approve(address(this), activeLoan.getId()); vm.prank(seaportAddr); custodian.generateOrder( address(this), new SpentItem[](0), activeDebt, abi.encode(Actions.Repayment, activeLoan) ); } - //TODO: add assertions - - function testGenerateOrderRepayERC1155WithRevert() public { - // 1155 - Starport.Loan memory originationDetails = _generateOriginationDetails( - _getERC1155SpentItem(erc1155s[0]), _getERC20SpentItem(erc20s[0], borrowAmount), address(issuer) - ); - - Starport.Loan memory loan = - newLoan(originationDetails, bytes32(uint256(2)), bytes32(uint256(2)), address(issuer)); - skip(1); - - loan.toStorage(activeLoan); - vm.prank(seaportAddr); - //function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external; - vm.mockCallRevert( - address(issuer), - abi.encodeWithSelector( - LoanSettledCallback.onLoanSettled.selector, abi.encode(Actions.Repayment, activeLoan) - ), - new bytes(0) - ); - custodian.generateOrder( - activeLoan.borrower, new SpentItem[](0), activeDebt, abi.encode(Actions.Repayment, activeLoan) - ); - } function testGenerateOrdersWithLoanStartAtBlockTimestampInvalidLoan() public { // 1155 @@ -254,7 +250,6 @@ contract TestCustodian is StarportTest, DeepEq, MockCall { newLoan(originationDetails, bytes32(uint256(2)), bytes32(uint256(2)), address(issuer)); loan.toStorage(activeLoan); vm.prank(seaportAddr); - //function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external; vm.expectRevert(abi.encodeWithSelector(Custodian.InvalidLoan.selector)); custodian.generateOrder( activeLoan.borrower, new SpentItem[](0), activeDebt, abi.encode(Actions.Repayment, activeLoan) @@ -395,18 +390,28 @@ contract TestCustodian is StarportTest, DeepEq, MockCall { vm.stopPrank(); } - function testGenerateOrderInvalidHandlerExecution() public { + function testGenerateOrderInvalidPostSettlement() public { vm.startPrank(seaportAddr); bytes memory context = abi.encode(Actions.Settlement, activeLoan); mockStatusCall(activeLoan.terms.status, false); mockSettlementCall(activeLoan.terms.settlement, new ReceivedItem[](0), address(activeLoan.terms.settlement)); - mockHandlerExecuteFail(activeLoan.terms.settlement); - vm.expectRevert(abi.encodeWithSelector(Custodian.InvalidHandlerExecution.selector)); + mockPostSettlementFail(activeLoan.terms.settlement); + vm.expectRevert(abi.encodeWithSelector(Custodian.InvalidPostSettlement.selector)); custodian.generateOrder(alice, new SpentItem[](0), activeDebt, context); vm.stopPrank(); } + function testGenerateOrderInvalidPostRepayment() public { + bytes memory context = abi.encode(Actions.Repayment, activeLoan); + mockStatusCall(activeLoan.terms.status, true); + // mockSettlementCall(activeLoan.terms.settlement, new ReceivedItem[](0), address(activeLoan.terms.settlement)); + mockPostRepaymentFail(activeLoan.terms.settlement); + vm.expectRevert(abi.encodeWithSelector(Custodian.InvalidPostRepayment.selector)); + vm.prank(seaportAddr); + custodian.generateOrder(activeLoan.borrower, new SpentItem[](0), activeDebt, context); + } + function testPreviewOrderRepay() public { mockStatusCall(activeLoan.terms.status, true); mockSettlementCall(activeLoan.terms.settlement, new ReceivedItem[](0), address(0)); diff --git a/test/unit-testing/TestPricing.sol b/test/unit-testing/TestPricing.sol index 988928af..dadd0e25 100644 --- a/test/unit-testing/TestPricing.sol +++ b/test/unit-testing/TestPricing.sol @@ -35,7 +35,7 @@ contract TestSimpleInterestPricing is StarportTest, DeepEq { collateral: newCollateral, debt: newDebt, terms: Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: abi.encode( diff --git a/test/unit-testing/TestStarport.sol b/test/unit-testing/TestStarport.sol index 08ac5fc1..aa343dd2 100644 --- a/test/unit-testing/TestStarport.sol +++ b/test/unit-testing/TestStarport.sol @@ -164,6 +164,11 @@ contract TestStarport is StarportTest, DeepEq { SP.unpause(); } + function testApplyRefinanceConsiderationToLoanMalformed() public { + vm.expectRevert(Starport.MalformedRefinance.selector); + SP.applyRefinanceConsiderationToLoan(activeLoan, new SpentItem[](0), new SpentItem[](0), ""); + } + function testInitializedFlagSetProperly() public { activeLoan.borrower = address(0); assert(SP.inactive(activeLoan.getId())); diff --git a/test/unit-testing/TestV1Settlement.sol b/test/unit-testing/TestV1Settlement.sol index 5bd57721..96d8f641 100644 --- a/test/unit-testing/TestV1Settlement.sol +++ b/test/unit-testing/TestV1Settlement.sol @@ -18,7 +18,7 @@ contract TestAstariaV1Settlement is AstariaV1Test, DeepEq { function testGetSettlementFailedDutchAuction() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -48,7 +48,7 @@ contract TestAstariaV1Settlement is AstariaV1Test, DeepEq { function testGetSettlementLoanNotRecalled() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -65,7 +65,7 @@ contract TestAstariaV1Settlement is AstariaV1Test, DeepEq { function testGetSettlementDutchAuctionSettlementAbove() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -121,7 +121,7 @@ contract TestAstariaV1Settlement is AstariaV1Test, DeepEq { function testGetAuctionStartNotStarted() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -137,7 +137,7 @@ contract TestAstariaV1Settlement is AstariaV1Test, DeepEq { function testGetAuctionStart() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -166,7 +166,7 @@ contract TestAstariaV1Settlement is AstariaV1Test, DeepEq { function testGetCurrentAuctionPrice() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -196,7 +196,7 @@ contract TestAstariaV1Settlement is AstariaV1Test, DeepEq { function testGetCurrentAuctionPriceNoAuction() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -211,25 +211,9 @@ contract TestAstariaV1Settlement is AstariaV1Test, DeepEq { uint256 currentAuctionPrice = AstariaV1Settlement(loan.terms.settlement).getCurrentAuctionPrice(loan); } - function testV1SettlementHandlerExecute() public { - Starport.Terms memory terms = Starport.Terms({ - status: address(hook), - settlement: address(settlement), - pricing: address(pricing), - pricingData: defaultPricingData, - settlementData: defaultSettlementData, - statusData: defaultStatusData - }); - Starport.Loan memory loan = - _createLoan721Collateral20Debt({lender: lender.addr, borrowAmount: 1e18, terms: terms}); - - vm.expectRevert(abi.encodeWithSelector(AstariaV1Settlement.ExecuteHandlerNotImplemented.selector)); - AstariaV1Settlement(loan.terms.settlement).execute(loan, address(this)); - } - function testV1SettlementHandlerValidate() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -244,7 +228,7 @@ contract TestAstariaV1Settlement is AstariaV1Test, DeepEq { function testV1SettlementHandlerValidateInvalidHandler() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, diff --git a/test/unit-testing/TestV1Status.sol b/test/unit-testing/TestV1Status.sol index 1249468b..617802ed 100644 --- a/test/unit-testing/TestV1Status.sol +++ b/test/unit-testing/TestV1Status.sol @@ -20,7 +20,7 @@ contract TestAstariaV1Status is AstariaV1Test, DeepEq { function testIsActive() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -35,7 +35,7 @@ contract TestAstariaV1Status is AstariaV1Test, DeepEq { function testIsRecalledInsideWindow() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -63,7 +63,7 @@ contract TestAstariaV1Status is AstariaV1Test, DeepEq { function testInvalidRecallLoanDoesNotExist() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -87,7 +87,7 @@ contract TestAstariaV1Status is AstariaV1Test, DeepEq { function testInvalidRecallInvalidStakeType() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -113,7 +113,7 @@ contract TestAstariaV1Status is AstariaV1Test, DeepEq { function testCannotRecallTwice() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -137,7 +137,7 @@ contract TestAstariaV1Status is AstariaV1Test, DeepEq { function testIsRecalledOutsideWindow() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -162,7 +162,7 @@ contract TestAstariaV1Status is AstariaV1Test, DeepEq { function testGenerateRecallConsideration() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -201,7 +201,7 @@ contract TestAstariaV1Status is AstariaV1Test, DeepEq { function testRecallRateEmptyRecall() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -219,7 +219,7 @@ contract TestAstariaV1Status is AstariaV1Test, DeepEq { function testRecallRateActiveRecall() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -245,7 +245,7 @@ contract TestAstariaV1Status is AstariaV1Test, DeepEq { function testCannotWithdrawWithdrawDoesNotExist() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, @@ -261,7 +261,7 @@ contract TestAstariaV1Status is AstariaV1Test, DeepEq { function testCannotWithdrawLoanHasNotBeenRefinanced() public { Starport.Terms memory terms = Starport.Terms({ - status: address(hook), + status: address(status), settlement: address(settlement), pricing: address(pricing), pricingData: defaultPricingData, diff --git a/test/utils/MockCall.sol b/test/utils/MockCall.sol index 785b117b..21526f28 100644 --- a/test/utils/MockCall.sol +++ b/test/utils/MockCall.sol @@ -31,7 +31,11 @@ abstract contract MockCall is TestBase { ); } - function mockHandlerExecuteFail(address settlement) public { - vm.mockCall(settlement, abi.encodeWithSelector(Settlement.execute.selector), abi.encode(bytes4(0))); + function mockPostSettlementFail(address settlement) public { + vm.mockCall(settlement, abi.encodeWithSelector(Settlement.postSettlement.selector), abi.encode(bytes4(0))); + } + + function mockPostRepaymentFail(address settlement) public { + vm.mockCall(settlement, abi.encodeWithSelector(Settlement.postRepayment.selector), abi.encode(bytes4(0))); } }