diff --git a/package.json b/package.json index 04de2fa..1c170f5 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ }, "scripts": { "prepare": "husky install", - "snapshot": "forge snapshot --diff --no-match-path *fuzz*" + "snapshot": "forge snapshot --diff --no-match-path *fuzz*", + "test": "forge test --no-match-path *fuzz*" }, "dependencies": { "@mermaid-js/mermaid-cli": "^10.6.1", diff --git a/src/enforcers/AstariaV1BorrowerEnforcer.sol b/src/enforcers/AstariaV1BorrowerEnforcer.sol index 860df5b..2c6b204 100644 --- a/src/enforcers/AstariaV1BorrowerEnforcer.sol +++ b/src/enforcers/AstariaV1BorrowerEnforcer.sol @@ -27,6 +27,7 @@ contract AstariaV1BorrowerEnforcer is BorrowerEnforcer { error DebtBundlesNotSupported(); error LoanAmountOutOfBounds(); error LoanRateExceedsCurrentRate(); + error AmountExceedsCaveatCollateral(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRUCTS */ @@ -93,13 +94,25 @@ contract AstariaV1BorrowerEnforcer is BorrowerEnforcer { revert LoanRateExceedsCurrentRate(); } + BorrowerEnforcer.Details memory caveatDetails = v1Details.details; // Update the caveat loan rate and amount - Starport.Loan memory caveatLoan = v1Details.details.loan; + Starport.Loan memory caveatLoan = caveatDetails.loan; + uint256 i = 0; + for (; i < caveatLoan.collateral.length;) { + if (caveatLoan.collateral[i].amount < loan.collateral[i].amount) { + revert AmountExceedsCaveatCollateral(); + } else { + caveatLoan.collateral[i].amount = loan.collateral[i].amount; + } + unchecked { + ++i; + } + } AstariaV1Lib.setBasePricingRate(caveatLoan.terms.pricingData, loanRate); caveatLoan.debt[0].amount = loanAmount; // Hash match w/ expected issuer - _validate(additionalTransfers, loan, v1Details.details); + _validate(additionalTransfers, loan, caveatDetails); selector = CaveatEnforcer.validate.selector; } diff --git a/test/TestV1BorrowerEnforcer.sol b/test/TestV1BorrowerEnforcer.sol index c0919ba..38b7227 100644 --- a/test/TestV1BorrowerEnforcer.sol +++ b/test/TestV1BorrowerEnforcer.sol @@ -109,7 +109,7 @@ contract TestV1BorrowerEnforcer is AstariaV1Test, AstariaV1BorrowerEnforcer { borrowerEnforcer.validate(new AdditionalTransfer[](0), loan, abi.encode(details)); } - function testV1BorrowerEnforcerAmountOOB() public { + function testV1BorrowerEnforcerDebtAmountOOB() public { Starport.Loan memory loan = generateDefaultLoanTerms(); AstariaV1BorrowerEnforcer.V1BorrowerDetails memory details = AstariaV1BorrowerEnforcer.V1BorrowerDetails({ @@ -132,6 +132,37 @@ contract TestV1BorrowerEnforcer is AstariaV1Test, AstariaV1BorrowerEnforcer { borrowerEnforcer.validate(new AdditionalTransfer[](0), loan, abi.encode(details)); } + function testV1BorrowerEnforcerCollateralAmountOOB() public { + Starport.Loan memory loan = generateDefaultLoanTerms(); + + loan.collateral[0] = SpentItem({ + itemType: ItemType.ERC20, + token: address(erc20s[1]), + amount: 50, + identifier: 0 // 0 for ERC20 + }); + + AstariaV1BorrowerEnforcer.V1BorrowerDetails memory details = AstariaV1BorrowerEnforcer.V1BorrowerDetails({ + startTime: block.timestamp, + endTime: block.timestamp + 10, + startRate: endRate / 2, + minAmount: loan.debt[0].amount, + maxAmount: loan.debt[0].amount * 2, + details: BorrowerEnforcer.Details(loanCopy(loan)) + }); + loan.terms.pricingData = abi.encode(BasePricing.Details({carryRate: 0, rate: endRate / 2, decimals: 18})); + + loan.collateral[0].amount++; + + // amount above the expected collateral amount + vm.expectRevert(AmountExceedsCaveatCollateral.selector); + borrowerEnforcer.validate(new AdditionalTransfer[](0), loan, abi.encode(details)); + + // amount below the expected collateral amount + loan.collateral[0].amount -= 2; + borrowerEnforcer.validate(new AdditionalTransfer[](0), loan, abi.encode(details)); + } + // Test rate more than current function testV1BorrowerEnforcerRateGTCurrent() public { Starport.Loan memory loan = generateDefaultLoanTerms();