diff --git a/.gas-snapshot b/.gas-snapshot index 17ffae23..837bb5a9 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -29,8 +29,8 @@ TestBorrowerEnforcer:testBEValidLoanTermsAnyIssuer() (gas: 72343) TestCustodian:testCannotLazyMintTwice() (gas: 82105) TestCustodian:testCannotMintInvalidLoanInvalidCustodian() (gas: 72477) TestCustodian:testCannotMintInvalidLoanValidCustodian() (gas: 77943) -TestCustodian:testCustodianCannotBeAuthorized() (gas: 141967) -TestCustodian:testCustodySelector() (gas: 2717132) +TestCustodian:testCustodianCannotBeAuthorized() (gas: 142026) +TestCustodian:testCustodySelector() (gas: 2732377) TestCustodian:testDefaultCustodySelectorRevert() (gas: 72478) TestCustodian:testGenerateOrderInvalidPostRepayment() (gas: 172899) TestCustodian:testGenerateOrderInvalidPostSettlement() (gas: 163178) @@ -47,22 +47,22 @@ TestCustodian:testGenerateOrderSettlementNoActiveLoan() (gas: 163374) TestCustodian:testGenerateOrderSettlementUnauthorized() (gas: 101809) TestCustodian:testGenerateOrdersWithLoanStartAtBlockTimestampInvalidLoan() (gas: 461511) TestCustodian:testGetBorrower() (gas: 78603) -TestCustodian:testInvalidAction() (gas: 179690) -TestCustodian:testInvalidActionRepayInActiveLoan() (gas: 130036) -TestCustodian:testInvalidActionSettleActiveLoan() (gas: 129973) -TestCustodian:testInvalidEncodedData() (gas: 26160) +TestCustodian:testInvalidAction() (gas: 179808) +TestCustodian:testInvalidActionRepayInActiveLoan() (gas: 130095) +TestCustodian:testInvalidActionSettleActiveLoan() (gas: 130032) +TestCustodian:testInvalidEncodedData() (gas: 26219) TestCustodian:testMintWithApprovalSetAsBorrower() (gas: 366740) TestCustodian:testMintWithApprovalSetAsBorrowerInvalidLoan() (gas: 64505) TestCustodian:testMintWithApprovalSetNotAuthorized() (gas: 66842) TestCustodian:testName() (gas: 7077) TestCustodian:testNonPayableFunctions() (gas: 215289) -TestCustodian:testOnlySeaport() (gas: 17918) -TestCustodian:testPreviewOrderNoActiveLoan() (gas: 105670) -TestCustodian:testPreviewOrderRepay() (gas: 229793) -TestCustodian:testPreviewOrderSettlement() (gas: 191754) -TestCustodian:testPreviewOrderSettlementInvalidFufliller() (gas: 108161) -TestCustodian:testPreviewOrderSettlementInvalidRepayer() (gas: 116854) -TestCustodian:testRatifyOrder() (gas: 183880) +TestCustodian:testOnlySeaport() (gas: 17915) +TestCustodian:testPreviewOrderNoActiveLoan() (gas: 105729) +TestCustodian:testPreviewOrderRepay() (gas: 231938) +TestCustodian:testPreviewOrderSettlement() (gas: 191813) +TestCustodian:testPreviewOrderSettlementInvalidFufliller() (gas: 110326) +TestCustodian:testPreviewOrderSettlementInvalidRepayer() (gas: 116902) +TestCustodian:testRatifyOrder() (gas: 183877) TestCustodian:testSeaportMetadata() (gas: 8588) TestCustodian:testSupportsInterface() (gas: 9428) TestCustodian:testSymbol() (gas: 7194) @@ -73,10 +73,10 @@ TestLenderEnforcer:testLERevertInvalidLoanTerms() (gas: 81096) TestLenderEnforcer:testLEValidLoanTerms() (gas: 72169) TestLenderEnforcer:testLEValidLoanTermsAnyBorrower() (gas: 72234) TestLenderEnforcer:testLEValidLoanTermsWithAdditionalTransfers() (gas: 73525) -TestLoanCombinations:testLoan20For721SimpleInterestDutchFixedRepay() (gas: 592496) -TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 599709) -TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 589927) -TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 579744) +TestLoanCombinations:testLoan20For721SimpleInterestDutchFixedRepay() (gas: 592542) +TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 599755) +TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 589973) +TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 579790) TestNewLoan:testBuyNowPayLater() (gas: 3018513) TestNewLoan:testNewLoanAs1271ProxyAccountSender() (gas: 874179) TestNewLoan:testNewLoanAs1271ProxyAccountThirdPartyFiller() (gas: 885204) @@ -89,12 +89,12 @@ TestPausableNonReentrant:testNotOwner() (gas: 21276) TestPausableNonReentrant:testPauseAndUnpause() (gas: 22643) TestPausableNonReentrant:testReentrancy() (gas: 15404) TestPausableNonReentrant:testUnpauseWhenNotPaused() (gas: 12604) -TestRepayLoan:testRepayLoanApprovedRepayer() (gas: 666673) -TestRepayLoan:testRepayLoanBase() (gas: 599539) +TestRepayLoan:testRepayLoanApprovedRepayer() (gas: 666719) +TestRepayLoan:testRepayLoanBase() (gas: 599585) TestRepayLoan:testRepayLoanGenerateOrderNotSeaport() (gas: 438777) -TestRepayLoan:testRepayLoanInSettlement() (gas: 585633) -TestRepayLoan:testRepayLoanInvalidRepayer() (gas: 603643) -TestRepayLoan:testRepayLoanThatDoesNotExist() (gas: 857698) +TestRepayLoan:testRepayLoanInSettlement() (gas: 585692) +TestRepayLoan:testRepayLoanInvalidRepayer() (gas: 603689) +TestRepayLoan:testRepayLoanThatDoesNotExist() (gas: 857790) TestSimpleInterestPricing:test_calculateInterest() (gas: 869870) TestSimpleInterestPricing:test_getPaymentConsideration() (gas: 916886) TestSimpleInterestPricing:test_getRefinanceConsideration() (gas: 907796) @@ -103,7 +103,7 @@ TestStarport:testAcquireTokensSuccess() (gas: 162844) TestStarport:testActive() (gas: 69358) TestStarport:testAdditionalTransfers() (gas: 300755) TestStarport:testAdditionalTransfersOriginate() (gas: 275540) -TestStarport:testAdditionalTransfersRefinance() (gas: 218107) +TestStarport:testAdditionalTransfersRefinance() (gas: 218120) TestStarport:testApplyRefinanceConsiderationToLoanMalformed() (gas: 129484) TestStarport:testCannotIssueSameLoanTwice() (gas: 364125) TestStarport:testCannotOriginateWhilePaused() (gas: 73479) @@ -115,13 +115,13 @@ TestStarport:testDefaultFeeRake2() (gas: 445821) TestStarport:testDefaultFeeRakeExoticDebt() (gas: 394368) TestStarport:testEIP712Signing() (gas: 83109) TestStarport:testExcessiveFeeRake() (gas: 19992) -TestStarport:testExoticDebtWithCustomPricingAndRepayment() (gas: 1237783) -TestStarport:testExoticDebtWithCustomPricingAndSettlement() (gas: 1695822) +TestStarport:testExoticDebtWithCustomPricingAndRepayment() (gas: 1237829) +TestStarport:testExoticDebtWithCustomPricingAndSettlement() (gas: 1695881) TestStarport:testExoticDebtWithNoCaveatsNotAsBorrower() (gas: 376639) TestStarport:testIncrementCaveatNonce() (gas: 35117) TestStarport:testInitializedFlagSetProperly() (gas: 67372) TestStarport:testInvalidAdditionalTransfersOriginate() (gas: 230426) -TestStarport:testInvalidAdditionalTransfersRefinance() (gas: 170667) +TestStarport:testInvalidAdditionalTransfersRefinance() (gas: 170620) TestStarport:testInvalidAmountCollateral() (gas: 165968) TestStarport:testInvalidAmountCollateral721() (gas: 165968) TestStarport:testInvalidItemType() (gas: 151916) diff --git a/docs/mermaid/origination.mmd b/docs/mermaid/origination.mmd deleted file mode 100644 index 51cc7961..00000000 --- a/docs/mermaid/origination.mmd +++ /dev/null @@ -1,66 +0,0 @@ -sequenceDiagram - title Starport Origination Sequence Diagram - - - Box blue Parties - participant AdditionalTransferRecipient - participant Fulfiller - end - - Box green Orignation - participant Starport - participant CaveatEnforcer - end - - Box rgb(112,100,0) Assets - participant Borrower - participant Custodian - participant Lender - participant FeeRecipient - end - - Fulfiller->>Starport: originate - - opt Fulfiller is not Borrower - loop 1->n - Starport->>CaveatEnforcer: validate - end - end - opt Fulfiller is not Lender - loop 1->n - Starport->>CaveatEnforcer: validate - end - end - loop Transfer 1->n collateral items - Borrower->>Custodian: transfer collateral - end - opt Custodian is not default - Starport->>Custodian: custody (optional) - end - - alt Fees Disabled - loop Transfer 1->n debt items - Lender->>Borrower: transfer debt - end - else Fees Enabled - opt FeeItems length > 0 - loop Transfer 1->n fee items - Lender->>FeeRecipient: Move Fee to FeeRecipient - end - end - loop Transfer 1->n debt items - Lender->>Borrower: Move debt to Borrower - Fee - end - end - - opt AdditionalTransferItems length > 0 - loop 1->n - alt From is Borrower - Borrower->>AdditionalTransferRecipient: AdditionalTransferItem from Borrower => AdditionalTransferRecipient - else From is Lender - Lender->>AdditionalTransferRecipient: AdditionalTransferItem from Lender => AdditionalTransferRecipient - else From is F - Fulfiller->>AdditionalTransferRecipient: AdditionalTransferItem from Fulfiller => AdditionalTransferRecipient - end - end - end \ No newline at end of file diff --git a/docs/mermaid/origination.svg b/docs/mermaid/origination.svg deleted file mode 100644 index 87c92b23..00000000 --- a/docs/mermaid/origination.svg +++ /dev/null @@ -1 +0,0 @@ -AssetsOrignationPartiesFeeRecipientLenderCustodianBorrowerCaveatEnforcerStarportFulfillerAdditionalTransferRecipientFeeRecipientLenderCustodianBorrowerCaveatEnforcerStarportFulfillerAdditionalTransferRecipientloop[1->n]opt[Fulfiller is notBorrower]loop[1->n]opt[Fulfiller is notLender]loop[Transfer 1->ncollateral items]opt[Custodian is not default]loop[Transfer 1->n debt items]loop[Transfer 1->n fee items]opt[FeeItems length > 0]loop[Transfer 1->n debt items]alt[Fees Disabled][Fees Enabled]alt[From is Borrower][From is Lender][From is F]loop[1->n]opt[AdditionalTransferItems length > 0]originatevalidatevalidatetransfer collateralcustody (optional)transfer debtMove Fee to FeeRecipientMove debt to Borrower - FeeAdditionalTransferItem from Borrower => AdditionalTransferRecipientAdditionalTransferItem from Lender => AdditionalTransferRecipientAdditionalTransferItem from Fulfiller => AdditionalTransferRecipientStarport Origination Sequence Diagram \ No newline at end of file diff --git a/docs/mermaid/refinance.mmd b/docs/mermaid/refinance.mmd deleted file mode 100644 index fe9bb263..00000000 --- a/docs/mermaid/refinance.mmd +++ /dev/null @@ -1,55 +0,0 @@ -sequenceDiagram - title Starport Refinance Sequence Diagram - - - - Box blue - participant AdditionalTransferRecipient - participant F as Fulfiller - end - Box green - participant Starport - participant Pricing - participant Settlement - participant CaveatEnforcer - end - - Box rgb(112,100,0) - participant B as Borrower - participant R as New Lender - participant L as Original Lender - participant Originator as Original Originator - end - - F->>Starport: refinance - Starport->>Pricing: getRefinanceConsideration - Pricing->>Starport: (SpentItem[] ConsiderPayment, SpentItem[] CarryPayment, AdditionalTransfer[] AT) - - Starport->>Starport: _settleLoan - Starport->>Settlement: postRepayment - - loop Transfer 1->n ConsiderPayment items - R->>L: Move ConsiderPayment to Lender - end - opt CarryPayment length > 0 - R->>Originator: Move CarryPayment to Originator - end - - opt F is not Refinancer and F is not approved - loop Validate 1->n Caveats - Starport->>CaveatEnforcer: validate - end - end - opt AdditionalTransferItems length > 0 - Starport->>Starport: validateAdditionalTransfers - loop 1->n - alt From is Borrower - B->>AdditionalTransferRecipient: AdditionalTransferItem from Borrower -> AdditionalTransferRecipient - else From is Lender - R->>AdditionalTransferRecipient: AdditionalTransferItem from Refinancer -> AdditionalTransferRecipient - else From is F - F->>AdditionalTransferRecipient: AdditionalTransferItem from Fulfiller -> AdditionalTransferRecipient - end - end - end - Starport->>Starport: _issueLoan \ No newline at end of file diff --git a/docs/mermaid/refinance.svg b/docs/mermaid/refinance.svg deleted file mode 100644 index 298ed7dd..00000000 --- a/docs/mermaid/refinance.svg +++ /dev/null @@ -1 +0,0 @@ -Original OriginatorOriginal LenderNew LenderBorrowerCaveatEnforcerSettlementPricingStarportFulfillerAdditionalTransferRecipientOriginal OriginatorOriginal LenderNew LenderBorrowerCaveatEnforcerSettlementPricingStarportFulfillerAdditionalTransferRecipientloop[Transfer 1->n ConsiderPaymentitems]opt[CarryPayment length > 0]loop[Validate 1->n Caveats]opt[F is not Refinancer and F is not approved]alt[From is Borrower][From is Lender][From is F]loop[1->n]opt[AdditionalTransferItems length > 0]refinancegetRefinanceConsideration(SpentItem[] ConsiderPayment, SpentItem[] CarryPayment, AdditionalTransfer[] AT)_settleLoanpostRepaymentMove ConsiderPayment to LenderMove CarryPayment to OriginatorvalidatevalidateAdditionalTransfersAdditionalTransferItem from Borrower -> AdditionalTransferRecipientAdditionalTransferItem from Refinancer -> AdditionalTransferRecipientAdditionalTransferItem from Fulfiller -> AdditionalTransferRecipient_issueLoanStarport Refinance Sequence Diagram \ No newline at end of file diff --git a/docs/mermaid/settlement.mmd b/docs/mermaid/settlement.mmd deleted file mode 100644 index 6b7ed04b..00000000 --- a/docs/mermaid/settlement.mmd +++ /dev/null @@ -1,36 +0,0 @@ -sequenceDiagram - title Starport Settlement Sequence Diagram - Box green - participant F as Fulfiller - participant Seaport - end - Box rgb(112, 100, 0) - participant Custodian - participant Status - participant Pricing - participant Settlement - participant Starport - participant Authorized - end - F->>Seaport: fulfillAdvancedOrder/matchAdvancedOrder - Seaport->>Custodian: generateOrder - Custodian->>Status: isActive - Status->>Custodian: (true/false) - alt Action is Repayment and Status is Active - Custodian->>Pricing: getPaymentConsideration - Pricing->>Custodian: (SpentItem[] payment, SpentItem[] carry) - Custodian->>Starport: settle loan - Custodian->>Settlement: postRepayment - else Action Settlement and Custodian->>Status: isActive is false - Custodian->>Settlement: getSettlement - Settlement->>Custodian: (ReceivedItem[] consideration, address authorized) - alt authorized is address(0) || authorized is Fulfiller - Custodian->>Custodian: _setOfferApprovalsWithSeaport - else authorized is loan handler || authorized is loan issuer - Custodian->>Custodian: _moveCollateralToAuthorized - Custodian->>Authorized: transfer 1->n collateral - end - Custodian->>Starport: settle loan - Custodian->>Settlement: postSettlement - - end diff --git a/docs/mermaid/settlement.svg b/docs/mermaid/settlement.svg deleted file mode 100644 index 16f61f47..00000000 --- a/docs/mermaid/settlement.svg +++ /dev/null @@ -1 +0,0 @@ -AuthorizedStarportSettlementPricingStatusCustodianSeaportFulfillerAuthorizedStarportSettlementPricingStatusCustodianSeaportFulfilleralt[authorized is address(0) || authorized is Fulfiller][authorized is loan handler || authorized is loan issuer]alt[Action is Repayment and Status is Active][Action Settlement and Custodian->>Status: isActive is false]fulfillAdvancedOrder/matchAdvancedOrdergenerateOrderisActive(true/false)getPaymentConsideration(SpentItem[] payment, SpentItem[] carry)settle loanpostRepaymentgetSettlement(ReceivedItem[] consideration, address authorized)_setOfferApprovalsWithSeaport_moveCollateralToAuthorizedtransfer 1->n collateralsettle loanpostSettlementStarport Settlement Sequence Diagram \ No newline at end of file diff --git a/docs/trust_model.md b/docs/trust_model.md deleted file mode 100644 index 2aa3e425..00000000 --- a/docs/trust_model.md +++ /dev/null @@ -1,87 +0,0 @@ -# Starport Trust Model - -### Core contracts (Starport, Custodian) - -Core contracts are trusted by all transactors as a source of truth. - -The `Starport.Loan` struct hashes all data into the ERC-721 `tokenId`. Loans that `originate` in block must not be able to be repaid, refinanced, or settled. This ensures the uniqueness of the `tokenId`. - -#### Starport -- Enforcer Loan struct mutations though `tokenId` - - `tokenId` creation during originate - - `tokenId` deletion after repayment - - `tokenId` deletion after settlement - - `tokenId` creation and deletion during refinance - - Any time a `Starport.Loan` is modified, the `tokenId` must mutate - - Status record of a `tokenId` as `ACTIVE` or `INACTIVE` -- Enforce origination agreements - - Enforce `loan.collateral` transfers from the `loan.borrower` to `loan.custodian` - - Enforce `loan.debt` transfers from the `loan.lender` to the `loan.borrower` - - Enforce borrower caveats if `loan.borrower != msg.sender`, or borrower approved `msg.sender` - - Enforce lender caveats if `lender != msg.sender`, or lender approved `msg.sender` - - Create new `tokenId` - - Mint `tokenId` if the `loan.issuer` is a contract - - Enforce the transfer of `additionalTransfers` -- Enforce refinance - - Delete incoming `tokenId` - - Enforcer repayment transfers from `lender` (refinancing lender) to `loan.issuer` provided by `Pricing.getRefinanceConsideration()` - - Enforcer carry transfers from `lender` (refinancing lender) to `loan.originator` provided by `Pricing.getRefinanceConsideration()` - - prevent transfers of zero amounts - - prevent payments must match the `loan.debt.length` of the corresponding `tokenId` - - `carryPayment.length` must be`0` or equal to `loan.debt.length` - - Mutate `Starport.Loan` to reflect repayment of the original loan by the refinancing lender - - Enforce lender caveats if `lender != msg.sender`, or the lender has approved `msg.sender` - -#### Custodian -- Enforce return of the collateral -- Enforce repayment through Seaport -- Enforce settlement through Seaport - -### Modules (Pricing, Status, Settlement) -All modules are considered untrusted by the core contracts. Modules can optionally trust each other but it is not a strict requirement for implementation. -#### Pricing -##### getPaymentConsideration -```solidity - function getPaymentConsideration(Starport.Loan memory loan) - public - view - virtual - returns (SpentItem[] memory, SpentItem[] memory); -``` -- returns the consideration and carry that the collateral can be purchased for (repayment) from the `Custodian` through Seaport -- can return a consideration array of size 0, or an array element with an amount 0 - -##### getRefinanceConsideration -```solidity - function getRefinanceConsideration(Starport.Loan memory loan, bytes calldata newPricingData, address fulfiller) - external - view - virtual - returns (SpentItem[] memory paymentConsideration, SpentItem[] memory carryConsideration, AdditionalTransfer[] memory); -``` -- returns the paymentConsideration, carryConsideration, and additionalTransfers that must be paid to refinance a loan - - `paymentConsideration` will be transferred from the refinancing `lender` to the `loan.issuer` (original lender) - - `carryConsideration` will be transferred from the refinancing `lender` to the `loan.originator` - - `additionalTransfers` are optional transfers provided by the modules to enforce mechanisms specific to the module set - -#### Status - -##### isActive -```solidity -function isActive(Starport.Loan calldata loan) external view virtual returns (bool); -``` -- gives the status of whether a loan is in settlement or not -- Loans can go into and out of settlement dependent on dynamically, it is possible for a loan to go into a settlement through an immutable switch but the expectation for the trust model should be that it can waiver -- When `isActive` returns `false` the `loan.collateral` can be purchased though `Seaport` from the `Custodian` with the consideration returned from `Settlement.getSettlementConsideration` - -#### Settlement -##### getSettlementConsideration -```solidity - function getSettlementConsideration(Starport.Loan calldata loan) - public - view - virtual - returns (ReceivedItem[] memory consideration, address restricted); -``` -- returns consideration for the authorized (if address(0) authorized is any) to purchase to collateral though Seaport -- The returned array cannot have zero amounts, but can be size zero \ No newline at end of file diff --git a/ffi-scripts/test-origination-hash.ts b/ffi-scripts/test-origination-hash.ts index 341afe88..e1e2d1fc 100644 --- a/ffi-scripts/test-origination-hash.ts +++ b/ffi-scripts/test-origination-hash.ts @@ -1,8 +1,6 @@ -import { Address, hashTypedData, pad, Hex, hexToString, keccak256 } from "viem"; -import { privateKeyToAccount } from "viem/accounts"; +import { Address, hashTypedData, pad, Hex } from "viem"; import { decodeAbiParameters, parseAbiParameters } from "viem"; - const types = { Origination: [ { @@ -42,7 +40,6 @@ const types = { ] }; - const domain = (verifyingContract: Address, chainId: number) => ({ name: "Starport", version: "0", @@ -50,25 +47,14 @@ const domain = (verifyingContract: Address, chainId: number) => ({ verifyingContract }); -type caveatType = [`0x${string}`, `0x${string}`]; - const typeDataMessage = (account: Address, accountNonce: string, singleUse: boolean, salt: Hex, deadline: string, caveats: any) => ({ account: account, accountNonce: parseInt(accountNonce), singleUse: singleUse, salt: salt, deadline: deadline, caveats: caveats[0] }); -//verifying contract -//account -//singleUse -//salt -//deadline -//caveats - const args = process.argv.slice(2); const main = async () => { const [signerKeyRaw, verifyingContract, account, accountNonce, singleUse, salt, deadline, caveatsRaw, chainId] = args; - const signerKey: any = `${signerKeyRaw}`; - // const signer = privateKeyToAccount(signerKey);//anvil account 1 const caveats: any = decodeAbiParameters(parseAbiParameters("(address enforcer,bytes data)[]"), caveatsRaw as `0x${string}`); const hashData: any = { domain: domain(verifyingContract as Address, parseInt(chainId as Hex)), diff --git a/ffi-scripts/test-sign-typed-data.ts b/ffi-scripts/test-sign-typed-data.ts index da935fc3..783254ad 100644 --- a/ffi-scripts/test-sign-typed-data.ts +++ b/ffi-scripts/test-sign-typed-data.ts @@ -1,5 +1,5 @@ 'use strict'; -import { decodeAbiParameters, parseAbiParameters, createWalletClient, http, Address, hashTypedData, pad, Hex, hexToString, keccak256 } from "viem"; +import { decodeAbiParameters, parseAbiParameters, createWalletClient, http, Address, pad, Hex } from "viem"; import { mainnet } from 'viem/chains' diff --git a/foundry.toml b/foundry.toml index a5690980..98f335b7 100644 --- a/foundry.toml +++ b/foundry.toml @@ -4,8 +4,6 @@ out = "out" libs = ["lib"] ignored_error_codes = [2018, 9302, 5574] -fs_permissions = [{ access = "read-write", path = "./"}] - [profile.default.fuzz] include_storage = false runs = 10000 diff --git a/lib/seaport b/lib/seaport index 50a0c096..4f4e7c20 160000 --- a/lib/seaport +++ b/lib/seaport @@ -1 +1 @@ -Subproject commit 50a0c09621f90196e8d07dbfb6c564256a241e66 +Subproject commit 4f4e7c205b957b91bc74f93d69838c9c32eece40 diff --git a/src/Custodian.sol b/src/Custodian.sol index ee6c5062..0623d52a 100644 --- a/src/Custodian.sol +++ b/src/Custodian.sol @@ -191,20 +191,14 @@ contract Custodian is ERC721, ContractOffererInterface { /** * @dev Generates the order for this contract offerer - * @param offer The address of the contract fulfiller - * @param consideration The maximum amount of items to be spent by the order - * @param context The context of the order - * @param orderHashes The context of the order - * @param contractNonce The context of the order * @return ratifyOrderMagicValue The magic value returned by the ratify */ - function ratifyOrder( - SpentItem[] calldata offer, - ReceivedItem[] calldata consideration, - bytes calldata context, // encoded based on the schemaID - bytes32[] calldata orderHashes, - uint256 contractNonce - ) external onlySeaport returns (bytes4 ratifyOrderMagicValue) { + function ratifyOrder(SpentItem[] calldata, ReceivedItem[] calldata, bytes calldata, bytes32[] calldata, uint256) + external + view + onlySeaport + returns (bytes4 ratifyOrderMagicValue) + { ratifyOrderMagicValue = ContractOffererInterface.ratifyOrder.selector; } @@ -237,7 +231,12 @@ contract Custodian is ERC721, ContractOffererInterface { (SpentItem[] memory payment, SpentItem[] memory carry) = Pricing(loan.terms.pricing).getPaymentConsideration(loan); - consideration = StarportLib.mergeSpentItemsToReceivedItems(payment, loan.issuer, carry, loan.originator); + consideration = StarportLib.mergeSpentItemsToReceivedItems({ + payment: payment, + paymentRecipient: loan.issuer, + carry: carry, + carryRecipient: loan.originator + }); _settleLoan(loan); _postRepaymentExecute(loan, fulfiller); @@ -303,22 +302,21 @@ contract Custodian is ERC721, ContractOffererInterface { } /** - * @dev Previews the order for this contract offerer. - * @param caller The address of the contract fulfiller. - * @param fulfiller The address of the contract fulfiller. - * @param minimumReceived The minimum the fulfiller must receive. - * @param maximumSpent The most a fulfiller will spend - * @param context The context of the order. - * @return offer The items spent by the order. - * @return consideration The items received by the order. + * @dev Previews the order for this contract offerer + * @param caller The address of the seaport contract + * @param fulfiller The address of the contract fulfiller + * @param context The context of the order + * @return offer The items spent by the order + * @return consideration The items received by the order */ function previewOrder( address caller, address fulfiller, - SpentItem[] calldata minimumReceived, - SpentItem[] calldata maximumSpent, + SpentItem[] calldata, + SpentItem[] calldata, bytes calldata context // Encoded based on the schemaID ) public view returns (SpentItem[] memory offer, ReceivedItem[] memory consideration) { + if (caller != address(seaport)) revert NotSeaport(); (Command memory close) = abi.decode(context, (Command)); Starport.Loan memory loan = close.loan; if (loan.start == block.timestamp || SP.closed(loan.getId())) { @@ -326,15 +324,19 @@ contract Custodian is ERC721, ContractOffererInterface { } bool loanActive = Status(loan.terms.status).isActive(loan, close.extraData); if (close.action == Actions.Repayment && loanActive) { - address borrower = getBorrower(loan); - if (fulfiller != borrower && fulfiller != _getApproved(loan.getId())) { + if (fulfiller != getBorrower(loan) && fulfiller != _getApproved(loan.getId())) { revert InvalidRepayer(); } offer = loan.collateral; (SpentItem[] memory payment, SpentItem[] memory carry) = Pricing(loan.terms.pricing).getPaymentConsideration(loan); - consideration = StarportLib.mergeSpentItemsToReceivedItems(payment, loan.issuer, carry, loan.originator); + consideration = StarportLib.mergeSpentItemsToReceivedItems({ + payment: payment, + paymentRecipient: loan.issuer, + carry: carry, + carryRecipient: loan.originator + }); } else if (close.action == Actions.Settlement && !loanActive) { address authorized; (consideration, authorized) = Settlement(loan.terms.settlement).getSettlementConsideration(loan); diff --git a/src/Starport.sol b/src/Starport.sol index 021f47f0..24c2cce6 100644 --- a/src/Starport.sol +++ b/src/Starport.sol @@ -418,7 +418,7 @@ contract Starport is PausableNonReentrant { /** * @dev Helper to hash a caveat with a salt and nonce * @param account The account that is originating the loan - * @param singleUse Whether or not the caveat is single use + * @param singleUse Whether to invalidate the salt after validation * @param salt The salt to use * @param deadline The deadline of the caveat * @param caveats The caveats to hash @@ -471,18 +471,18 @@ contract Starport is PausableNonReentrant { } /** - * @dev Helper to check if a loan is active + * @dev Helper to check if a loan is open * @param loanId The id of the loan - * @return bool True if the loan is active + * @return bool True if the loan is open */ function open(uint256 loanId) public view returns (bool) { return loanState[loanId] == LOAN_OPEN_FLAG; } /** - * @dev Helper to check if a loan is inactive + * @dev Helper to check if a loan is closed * @param loanId The id of the loan - * @return bool True if the loan is inactive + * @return bool True if the loan is closed */ function closed(uint256 loanId) public view returns (bool) { return loanState[loanId] == LOAN_CLOSED_FLAG; @@ -493,8 +493,8 @@ contract Starport is PausableNonReentrant { /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** - * @dev Settle the loan - * @param loan The the loan that is settled + * @dev Calls postRepayment hook on loan Settlement module + * @param loan The the loan that is being refrenced * @param fulfiller The address executing the settle */ function _postRepaymentExecute(Starport.Loan memory loan, address fulfiller) internal virtual { @@ -522,7 +522,7 @@ contract Starport is PausableNonReentrant { } /** - * @dev Internal method to validate additional transfers + * @dev Internal method to validate additional transfers, only transfer from lender and fullfiller are valid * @param lender The lender of the loan * @param fulfiller The fulfiller of the loan * @param additionalTransfers The additional transfers to validate @@ -534,7 +534,8 @@ contract Starport is PausableNonReentrant { ) internal pure { uint256 i = 0; for (; i < additionalTransfers.length;) { - if (additionalTransfers[i].from != lender && additionalTransfers[i].from != fulfiller) { + address from = additionalTransfers[i].from; + if (from != lender && from != fulfiller) { revert UnauthorizedAdditionalTransferIncluded(); } unchecked { @@ -544,7 +545,7 @@ contract Starport is PausableNonReentrant { } /** - * @dev Internal method to validate additional transfers + * @dev Internal method to validate additional transfers, only transfers from borrower, lender, and fullfiller are valid * @param borrower The borrower of the loan * @param lender The lender of the loan * @param fulfiller The fulfiller of the loan diff --git a/src/lib/StarportLib.sol b/src/lib/StarportLib.sol index 5c74e8c1..a26bdbe0 100644 --- a/src/lib/StarportLib.sol +++ b/src/lib/StarportLib.sol @@ -325,10 +325,6 @@ library StarportLib { } } - /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ - /* PRIVATE INTERNAL FUNCTIONS */ - /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ - function _transferItem( ItemType itemType, address token, diff --git a/src/pricing/SimpleInterestPricing.sol b/src/pricing/SimpleInterestPricing.sol index 87165715..9aa9f653 100644 --- a/src/pricing/SimpleInterestPricing.sol +++ b/src/pricing/SimpleInterestPricing.sol @@ -64,13 +64,13 @@ contract SimpleInterestPricing is BasePricing { /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // @inheritdoc Validation - function validate(Starport.Loan calldata loan) external view override returns (bytes4) { + function validate(Starport.Loan calldata loan) external pure override returns (bytes4) { Details memory details = abi.decode(loan.terms.pricingData, (Details)); return (details.decimals > 0) ? Validation.validate.selector : bytes4(0xFFFFFFFF); } // @inheritdoc Pricing - function getRefinanceConsideration(Starport.Loan calldata loan, bytes memory newPricingData, address fulfiller) + function getRefinanceConsideration(Starport.Loan calldata loan, bytes memory newPricingData, address) external view virtual @@ -81,6 +81,7 @@ contract SimpleInterestPricing is BasePricing { AdditionalTransfer[] memory additionalConsideration ) { + (additionalConsideration); Details memory oldDetails = abi.decode(loan.terms.pricingData, (Details)); Details memory newDetails = abi.decode(newPricingData, (Details)); diff --git a/src/settlement/DutchAuctionSettlement.sol b/src/settlement/DutchAuctionSettlement.sol index ead92d13..fd6ffe54 100644 --- a/src/settlement/DutchAuctionSettlement.sol +++ b/src/settlement/DutchAuctionSettlement.sol @@ -85,7 +85,7 @@ abstract contract DutchAuctionSettlement is Settlement, AmountDeriver { } // @inheritdoc Settlement - function postRepayment(Starport.Loan calldata loan, address fulfiller) external virtual override returns (bytes4) { + function postRepayment(Starport.Loan calldata, address) external virtual override returns (bytes4) { return Settlement.postRepayment.selector; } @@ -103,7 +103,7 @@ abstract contract DutchAuctionSettlement is Settlement, AmountDeriver { /** * @dev Get the start of the auction - * @param loan The loan in question + * @param loan The loan being referenced * @return uint256 The start of the auction */ function getAuctionStart(Starport.Loan calldata loan) public view virtual returns (uint256); diff --git a/test/unit-testing/TestCustodian.sol b/test/unit-testing/TestCustodian.sol index 7643d7bb..eb667b80 100644 --- a/test/unit-testing/TestCustodian.sol +++ b/test/unit-testing/TestCustodian.sol @@ -430,7 +430,7 @@ contract TestCustodian is StarportTest, DeepEq, MockCall { mockSettlementCall(activeLoan.terms.settlement, new ReceivedItem[](0), address(0)); (SpentItem[] memory receivedOffer, ReceivedItem[] memory receivedCosideration) = custodian.previewOrder( - activeLoan.borrower, + address(consideration), activeLoan.borrower, new SpentItem[](0), activeDebt, @@ -490,7 +490,7 @@ contract TestCustodian is StarportTest, DeepEq, MockCall { mockSettlementCall(activeLoan.terms.settlement, new ReceivedItem[](0), address(1)); vm.expectRevert(abi.encodeWithSelector(Custodian.InvalidFulfiller.selector)); (SpentItem[] memory receivedOffer, ReceivedItem[] memory receivedConsideration) = custodian.previewOrder( - alice, + address(consideration), alice, new SpentItem[](0), activeDebt, @@ -505,7 +505,11 @@ contract TestCustodian is StarportTest, DeepEq, MockCall { mockSettlementCall(activeLoan.terms.settlement, new ReceivedItem[](0), address(0)); vm.expectRevert(abi.encodeWithSelector(Custodian.InvalidRepayer.selector)); (SpentItem[] memory receivedOffer, ReceivedItem[] memory receivedCosideration) = custodian.previewOrder( - alice, bob, new SpentItem[](0), activeDebt, abi.encode(Custodian.Command(Actions.Repayment, activeLoan, "")) + address(consideration), + bob, + new SpentItem[](0), + activeDebt, + abi.encode(Custodian.Command(Actions.Repayment, activeLoan, "")) ); }