From 23e714fb447e6db60439bab4f2e6cb47ab356962 Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Mon, 30 Oct 2023 18:37:48 -0500 Subject: [PATCH] Add enforcer unit testing --- .gas-snapshot | 72 ++++++++++++---------- src/enforcers/BorrowerEnforcer.sol | 12 ++-- src/enforcers/LenderEnforcer.sol | 9 ++- test/unit-testing/TestBorrowerEnforcer.sol | 46 ++++++++++++++ test/unit-testing/TestLenderEnforcer.sol | 61 ++++++++++++++++++ 5 files changed, 162 insertions(+), 38 deletions(-) create mode 100644 test/unit-testing/TestBorrowerEnforcer.sol create mode 100644 test/unit-testing/TestLenderEnforcer.sol diff --git a/.gas-snapshot b/.gas-snapshot index e873aaac..451a6b95 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,6 +1,10 @@ -TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallBase() (gas: 1039520) -TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLender() (gas: 691168) -TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLiquidation() (gas: 770737) +TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallBase() (gas: 1038509) +TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLender() (gas: 690656) +TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLiquidation() (gas: 770225) +TestBorrowerEnforcer:testBERevertAdditionalTransfers() (gas: 73101) +TestBorrowerEnforcer:testBERevertInvalidLoanTerms() (gas: 78338) +TestBorrowerEnforcer:testBEValidLoanTerms() (gas: 69429) +TestBorrowerEnforcer:testBEValidLoanTermsAnyIssuer() (gas: 69581) TestCustodian:testCannotLazyMintTwice() (gas: 76597) TestCustodian:testCannotMintInvalidLoanInvalidCustodian() (gas: 66883) TestCustodian:testCannotMintInvalidLoanValidCustodian() (gas: 72422) @@ -9,9 +13,9 @@ TestCustodian:testDefaultCustodySelectorRevert() (gas: 70105) TestCustodian:testGenerateOrderInvalidHandlerExecution() (gas: 132855) TestCustodian:testGenerateOrderRepay() (gas: 164375) TestCustodian:testGenerateOrderRepayAsRepayApprovedBorrower() (gas: 190022) -TestCustodian:testGenerateOrderRepayERC1155AndERC20AndNative() (gas: 843726) -TestCustodian:testGenerateOrderRepayERC1155AndERC20AndNativeHandlerAuthorized() (gas: 785358) -TestCustodian:testGenerateOrderRepayERC1155WithRevert() (gas: 518154) +TestCustodian:testGenerateOrderRepayERC1155AndERC20AndNative() (gas: 843192) +TestCustodian:testGenerateOrderRepayERC1155AndERC20AndNativeHandlerAuthorized() (gas: 784824) +TestCustodian:testGenerateOrderRepayERC1155WithRevert() (gas: 517887) TestCustodian:testGenerateOrderRepayInvalidHookAddress() (gas: 90249) TestCustodian:testGenerateOrderRepayInvalidHookReturnType() (gas: 84653) TestCustodian:testGenerateOrderRepayNotBorrower() (gas: 96449) @@ -39,40 +43,46 @@ TestCustodian:testSupportsInterface() (gas: 9428) TestCustodian:testSymbol() (gas: 7149) TestCustodian:testTokenURI() (gas: 64839) TestCustodian:testTokenURIInvalidLoan() (gas: 13218) -TestLoanCombinations:testLoan20For721SimpleInterestDutchFixedRepay() (gas: 530977) -TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 499814) -TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 549734) -TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 539558) -TestLoanCombinations:testLoanSimpleInterestEnglishFixed() (gas: 544218) -TestLoanManager:testCannotIssueSameLoanTwice() (gas: 331333) +TestLenderEnforcer:testLERevertAdditionalTransfersFromLender() (gas: 73760) +TestLenderEnforcer:testLERevertInvalidLoanTerms() (gas: 78385) +TestLenderEnforcer:testLEValidLoanTerms() (gas: 69429) +TestLenderEnforcer:testLEValidLoanTermsAnyBorrower() (gas: 69516) +TestLenderEnforcer:testLEValidLoanTermsWithAdditionalTransfers() (gas: 70757) +TestLoanCombinations:testLoan20For721SimpleInterestDutchFixedRepay() (gas: 530465) +TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 499302) +TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 549222) +TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 539046) +TestLoanCombinations:testLoanSimpleInterestEnglishFixed() (gas: 543706) +TestLoanManager:testAdditionalTransfers() (gas: 292861) +TestLoanManager:testCannotIssueSameLoanTwice() (gas: 330843) TestLoanManager:testCannotSettleInvalidLoan() (gas: 72594) TestLoanManager:testCannotSettleUnlessValidCustodian() (gas: 68772) TestLoanManager:testCaveatEnforcerRevert() (gas: 116699) -TestLoanManager:testDefaultFeeRake() (gas: 350119) -TestLoanManager:testExoticDebtWithNoCaveatsNotAsBorrower() (gas: 342776) -TestLoanManager:testInitializedFlagSetProperly() (gas: 65230) -TestLoanManager:testInvalidAmountCollateral() (gas: 152875) -TestLoanManager:testInvalidAmountCollateral721() (gas: 152995) -TestLoanManager:testInvalidAmountDebt() (gas: 177208) -TestLoanManager:testInvalidItemType() (gas: 138923) -TestLoanManager:testInvalidTransferLengthCollateral() (gas: 161136) -TestLoanManager:testInvalidTransferLengthDebt() (gas: 165669) +TestLoanManager:testDefaultFeeRake() (gas: 349807) +TestLoanManager:testExoticDebtWithNoCaveatsNotAsBorrower() (gas: 342553) +TestLoanManager:testInitializedFlagSetProperly() (gas: 65252) +TestLoanManager:testInvalidAmountCollateral() (gas: 152652) +TestLoanManager:testInvalidAmountCollateral721() (gas: 152750) +TestLoanManager:testInvalidAmountDebt() (gas: 176963) +TestLoanManager:testInvalidItemType() (gas: 138700) +TestLoanManager:testInvalidTransferLengthCollateral() (gas: 160891) +TestLoanManager:testInvalidTransferLengthDebt() (gas: 165424) TestLoanManager:testIssued() (gas: 67055) TestLoanManager:testName() (gas: 7184) -TestLoanManager:testNonDefaultCustodianCustodyCallFails() (gas: 190240) -TestLoanManager:testNonDefaultCustodianCustodyCallSuccess() (gas: 258491) -TestLoanManager:testNonPayableFunctions() (gas: 173071) -TestLoanManager:testOverrideFeeRake() (gas: 343912) -TestLoanManager:testSupportsInterface() (gas: 9159) +TestLoanManager:testNonDefaultCustodianCustodyCallFails() (gas: 189995) +TestLoanManager:testNonDefaultCustodianCustodyCallSuccess() (gas: 258268) +TestLoanManager:testNonPayableFunctions() (gas: 173093) +TestLoanManager:testOverrideFeeRake() (gas: 343645) +TestLoanManager:testSupportsInterface() (gas: 9181) TestLoanManager:testSymbol() (gas: 7127) -TestLoanManager:testTokenNoCodeCollateral() (gas: 137717) -TestLoanManager:testTokenNoCodeDebt() (gas: 170775) +TestLoanManager:testTokenNoCodeCollateral() (gas: 137472) +TestLoanManager:testTokenNoCodeDebt() (gas: 170530) TestLoanManager:testTokenURI() (gas: 64914) -TestLoanManager:testTokenURIInvalidLoan() (gas: 13309) +TestLoanManager:testTokenURIInvalidLoan() (gas: 13244) TestLoanManager:testTransferFromFail() (gas: 80088) TestNewLoan:testBuyNowPayLater() (gas: 208) -TestNewLoan:testNewLoanERC721CollateralDefaultTerms2():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 389501) -TestNewLoan:testNewLoanERC721CollateralLessDebtThanOffered():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 2259) +TestNewLoan:testNewLoanERC721CollateralDefaultTerms2() (gas: 388989) +TestNewLoan:testNewLoanERC721CollateralLessDebtThanOffered() (gas: 2259) TestNewLoan:testNewLoanRefinanceNew() (gas: 207) TestNewLoan:testSettleLoan() (gas: 163) TestRepayLoan:testRepayLoan() (gas: 207) diff --git a/src/enforcers/BorrowerEnforcer.sol b/src/enforcers/BorrowerEnforcer.sol index eab66f95..d228af66 100644 --- a/src/enforcers/BorrowerEnforcer.sol +++ b/src/enforcers/BorrowerEnforcer.sol @@ -13,19 +13,23 @@ contract BorrowerEnforcer is CaveatEnforcer { LoanManager.Loan loan; } + /// @notice Enforces that the loan terms are identical except for the issuer + /// @notice The issuer is allowed to be any address + /// @notice No additional transfers are permitted + /// @param additionalTransfers The additional transfers to be made + /// @param loan The loan terms + /// @param caveatData The borrowers encoded details function validate( ConduitTransfer[] calldata additionalTransfers, LoanManager.Loan calldata loan, bytes calldata caveatData ) public view virtual override { - bytes32 loanHash = keccak256(abi.encode(loan)); - Details memory details = abi.decode(caveatData, (Details)); - if (details.loan.borrower != loan.borrower) revert BorrowerOnlyEnforcer(); details.loan.issuer = loan.issuer; - if (loanHash != keccak256(abi.encode(details.loan))) revert InvalidLoanTerms(); + if (keccak256(abi.encode(loan)) != keccak256(abi.encode(details.loan))) revert InvalidLoanTerms(); + //Should additional transfers from the accounts other than the borrower be allowed? if (additionalTransfers.length > 0) revert InvalidAdditionalTransfer(); } } diff --git a/src/enforcers/LenderEnforcer.sol b/src/enforcers/LenderEnforcer.sol index c1b79710..4d81c414 100644 --- a/src/enforcers/LenderEnforcer.sol +++ b/src/enforcers/LenderEnforcer.sol @@ -13,15 +13,18 @@ contract LenderEnforcer is CaveatEnforcer { LoanManager.Loan loan; } + /// @notice Enforces that the loan terms are identical except for the borrower + /// @notice The borrower is allowed to be any address + /// @notice No additional transfers from the issuer are permitted + /// @param additionalTransfers The additional transfers to be made + /// @param loan The loan terms + /// @param caveatData The borrowers encoded details function validate( ConduitTransfer[] calldata additionalTransfers, LoanManager.Loan calldata loan, bytes calldata caveatData ) public view virtual override { - // bytes32 loanHash = keccak256(abi.encode(loan)); - Details memory details = abi.decode(caveatData, (Details)); - if (details.loan.issuer != loan.issuer) revert LenderOnlyEnforcer(); details.loan.borrower = loan.borrower; if (keccak256(abi.encode(loan)) != keccak256(abi.encode(details.loan))) { diff --git a/test/unit-testing/TestBorrowerEnforcer.sol b/test/unit-testing/TestBorrowerEnforcer.sol new file mode 100644 index 00000000..ba1b836c --- /dev/null +++ b/test/unit-testing/TestBorrowerEnforcer.sol @@ -0,0 +1,46 @@ +import "starport-test/StarPortTest.sol"; +import {BorrowerEnforcer} from "starport-core/enforcers/BorrowerEnforcer.sol"; +import {ConduitTransfer, ConduitItemType} from "seaport-types/src/conduit/lib/ConduitStructs.sol"; + +import "forge-std/console.sol"; + +contract TestBorrowerEnforcer is StarPortTest { + function testBERevertAdditionalTransfers() external { + ConduitTransfer[] memory additionalTransfers = new ConduitTransfer[](1); + additionalTransfers[0] = ConduitTransfer({ + token: address(0), + amount: 0, + to: address(0), + from: address(0), + identifier: 0, + itemType: ConduitItemType.ERC20 + }); + + LoanManager.Loan memory loan = generateDefaultLoanTerms(); + BorrowerEnforcer.Details memory details = BorrowerEnforcer.Details({loan: loan}); + vm.expectRevert(BorrowerEnforcer.InvalidAdditionalTransfer.selector); + borrowerEnforcer.validate(additionalTransfers, loan, abi.encode(details)); + } + + function testBERevertInvalidLoanTerms() external { + LoanManager.Loan memory loan = generateDefaultLoanTerms(); + + BorrowerEnforcer.Details memory details = BorrowerEnforcer.Details({loan: loan}); + details.loan.borrower = lender.addr; + vm.expectRevert(BorrowerEnforcer.InvalidLoanTerms.selector); + borrowerEnforcer.validate(new ConduitTransfer[](0), generateDefaultLoanTerms(), abi.encode(details)); + } + + function testBEValidLoanTerms() external view { + LoanManager.Loan memory loan = generateDefaultLoanTerms(); + borrowerEnforcer.validate(new ConduitTransfer[](0), loan, abi.encode(BorrowerEnforcer.Details({loan: loan}))); + } + + function testBEValidLoanTermsAnyIssuer() external view { + LoanManager.Loan memory loan = generateDefaultLoanTerms(); + BorrowerEnforcer.Details memory details = BorrowerEnforcer.Details({loan: loan}); + details.loan.issuer = address(0); + + borrowerEnforcer.validate(new ConduitTransfer[](0), loan, abi.encode(BorrowerEnforcer.Details({loan: loan}))); + } +} diff --git a/test/unit-testing/TestLenderEnforcer.sol b/test/unit-testing/TestLenderEnforcer.sol new file mode 100644 index 00000000..abf3acb6 --- /dev/null +++ b/test/unit-testing/TestLenderEnforcer.sol @@ -0,0 +1,61 @@ +import "starport-test/StarPortTest.sol"; +import {LenderEnforcer} from "starport-core/enforcers/LenderEnforcer.sol"; +import {ConduitTransfer, ConduitItemType} from "seaport-types/src/conduit/lib/ConduitStructs.sol"; + +import "forge-std/console.sol"; + +contract TestLenderEnforcer is StarPortTest { + function testLERevertAdditionalTransfersFromLender() external { + ConduitTransfer[] memory additionalTransfers = new ConduitTransfer[](1); + additionalTransfers[0] = ConduitTransfer({ + token: address(0), + amount: 0, + to: address(0), + from: lender.addr, + identifier: 0, + itemType: ConduitItemType.ERC20 + }); + + LoanManager.Loan memory loan = generateDefaultLoanTerms(); + + vm.expectRevert(LenderEnforcer.InvalidAdditionalTransfer.selector); + lenderEnforcer.validate(additionalTransfers, loan, abi.encode(LenderEnforcer.Details({loan: loan}))); + } + + function testLERevertInvalidLoanTerms() external { + LoanManager.Loan memory loan = generateDefaultLoanTerms(); + + LenderEnforcer.Details memory details = LenderEnforcer.Details({loan: loan}); + details.loan.custodian = borrower.addr; + vm.expectRevert(LenderEnforcer.InvalidLoanTerms.selector); + + lenderEnforcer.validate(new ConduitTransfer[](0), generateDefaultLoanTerms(), abi.encode(details)); + } + + function testLEValidLoanTermsWithAdditionalTransfers() external view { + ConduitTransfer[] memory additionalTransfers = new ConduitTransfer[](1); + additionalTransfers[0] = ConduitTransfer({ + token: address(0), + amount: 0, + to: address(0), + from: address(0), + identifier: 0, + itemType: ConduitItemType.ERC20 + }); + LoanManager.Loan memory loan = generateDefaultLoanTerms(); + lenderEnforcer.validate(additionalTransfers, loan, abi.encode(LenderEnforcer.Details({loan: loan}))); + } + + function testLEValidLoanTerms() external view { + LoanManager.Loan memory loan = generateDefaultLoanTerms(); + lenderEnforcer.validate(new ConduitTransfer[](0), loan, abi.encode(LenderEnforcer.Details({loan: loan}))); + } + + function testLEValidLoanTermsAnyBorrower() external view { + LoanManager.Loan memory loan = generateDefaultLoanTerms(); + LenderEnforcer.Details memory details = LenderEnforcer.Details({loan: loan}); + details.loan.borrower = address(0); + + lenderEnforcer.validate(new ConduitTransfer[](0), loan, abi.encode(LenderEnforcer.Details({loan: loan}))); + } +}