From 15f71cf0d6e9eb15f017ab38c961b3a88b897db6 Mon Sep 17 00:00:00 2001 From: justin <1539088+justingreenberg@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:55:10 -0500 Subject: [PATCH] Adds licensing, import conventions, inline documentation (#74) * chore(src): adds licensing, import conventions, inline documentation * fix: formatting * chore: update gas snapshot * feat: conventions and contract organization * feat: update snapshot * chore: cleanup comment * chore: update readme, add license --- .gas-snapshot | 94 ++-- README.md | 4 + src/BNPLHelper.sol | 79 ++- src/Custodian.sol | 384 ++++++------- src/Starport.sol | 519 ++++++++++-------- src/enforcers/BorrowerEnforcer.sol | 44 +- src/enforcers/BorrowerEnforcerBNPL.sol | 43 +- src/enforcers/CaveatEnforcer.sol | 43 +- src/enforcers/LenderEnforcer.sol | 33 +- src/interfaces/TokenReceiverInterface.sol | 27 + src/lib/PausableNonReentrant.sol | 27 + src/lib/RefStarportLib.sol | 41 +- src/lib/StarportLib.sol | 126 ++++- src/lib/Validation.sol | 32 +- src/originators/Originator.sol | 55 +- src/originators/StrategistOriginator.sol | 227 ++++---- src/pricing/BasePricing.sol | 77 ++- src/pricing/Pricing.sol | 72 ++- src/pricing/SimpleInterestPricing.sol | 67 ++- src/settlement/DutchAuctionSettlement.sol | 73 ++- .../FixedTermDutchAuctionSettlement.sol | 42 +- src/settlement/Settlement.sol | 75 ++- src/status/FixedTermStatus.sol | 35 ++ src/status/Status.sol | 49 +- 24 files changed, 1514 insertions(+), 754 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 4493cd12..9659f5ad 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,22 +1,22 @@ -IntegrationTestCaveats:testOriginateUnapprovedFulfiller() (gas: 327589) -IntegrationTestCaveats:testOriginateWBorrowerApproval() (gas: 281025) +IntegrationTestCaveats:testOriginateUnapprovedFulfiller() (gas: 327586) +IntegrationTestCaveats:testOriginateWBorrowerApproval() (gas: 281010) IntegrationTestCaveats:testOriginateWCaveatsAsBorrower() (gas: 303246) -IntegrationTestCaveats:testOriginateWCaveatsExpired() (gas: 157439) -IntegrationTestCaveats:testOriginateWCaveatsIncrementedNonce() (gas: 166170) -IntegrationTestCaveats:testOriginateWCaveatsInvalidSalt() (gas: 281363) -IntegrationTestCaveats:testOriginateWCaveatsInvalidSaltManual() (gas: 140101) -IntegrationTestCaveats:testOriginateWLenderApproval() (gas: 281057) +IntegrationTestCaveats:testOriginateWCaveatsExpired() (gas: 157436) +IntegrationTestCaveats:testOriginateWCaveatsIncrementedNonce() (gas: 166167) +IntegrationTestCaveats:testOriginateWCaveatsInvalidSalt() (gas: 281357) +IntegrationTestCaveats:testOriginateWCaveatsInvalidSaltManual() (gas: 140098) +IntegrationTestCaveats:testOriginateWLenderApproval() (gas: 281042) IntegrationTestCaveats:testRefinanceAsLender() (gas: 1043289) IntegrationTestCaveats:testRefinanceCaveatFailure() (gas: 395348) IntegrationTestCaveats:testRefinanceLoanStartAtBlockTimestampInvalidLoan() (gas: 342963) IntegrationTestCaveats:testRefinanceUnapprovedFulfiller() (gas: 443624) IntegrationTestCaveats:testRefinanceWCaveatsInvalidSalt() (gas: 364730) -IntegrationTestCaveats:testRefinanceWLenderApproval() (gas: 392349) -ModuleTesting:testFixedTermDutchAuctionSettlement() (gas: 433475) -ModuleTesting:testFixedTermDutchAuctionSettlementGetSettlementAuctionExpired() (gas: 436253) -ModuleTesting:testFixedTermDutchAuctionSettlementNotValid() (gas: 432487) -ModuleTesting:testFixedTermDutchAuctionSettlementValid() (gas: 433286) -ModuleTesting:testModuleValidation() (gas: 1269674) +IntegrationTestCaveats:testRefinanceWLenderApproval() (gas: 392337) +ModuleTesting:testFixedTermDutchAuctionSettlement() (gas: 433472) +ModuleTesting:testFixedTermDutchAuctionSettlementGetSettlementAuctionExpired() (gas: 436250) +ModuleTesting:testFixedTermDutchAuctionSettlementNotValid() (gas: 432484) +ModuleTesting:testFixedTermDutchAuctionSettlementValid() (gas: 433283) +ModuleTesting:testModuleValidation() (gas: 1269671) PausableNonReentrantImpl:test() (gas: 2442) PausableNonReentrantImpl:testReentrancy() (gas: 2735) TestBorrowerEnforcer:testBERevertAdditionalTransfersFromBorrower() (gas: 76318) @@ -32,8 +32,8 @@ TestCustodian:testGenerateOrderInvalidPostRepayment() (gas: 172968) TestCustodian:testGenerateOrderInvalidPostSettlement() (gas: 163091) TestCustodian:testGenerateOrderRepay() (gas: 177123) TestCustodian:testGenerateOrderRepayAsRepayApprovedBorrower() (gas: 193592) -TestCustodian:testGenerateOrderRepayERC1155AndERC20() (gas: 868471) -TestCustodian:testGenerateOrderRepayERC1155AndERC20HandlerAuthorized() (gas: 798132) +TestCustodian:testGenerateOrderRepayERC1155AndERC20() (gas: 868465) +TestCustodian:testGenerateOrderRepayERC1155AndERC20HandlerAuthorized() (gas: 798126) TestCustodian:testGenerateOrderRepayInvalidHookAddress() (gas: 97601) TestCustodian:testGenerateOrderRepayInvalidHookReturnType() (gas: 91984) TestCustodian:testGenerateOrderRepayNotBorrower() (gas: 106839) @@ -41,7 +41,7 @@ TestCustodian:testGenerateOrderSettlement() (gas: 154846) TestCustodian:testGenerateOrderSettlementHandlerAuthorized() (gas: 160243) TestCustodian:testGenerateOrderSettlementNoActiveLoan() (gas: 163308) TestCustodian:testGenerateOrderSettlementUnauthorized() (gas: 101791) -TestCustodian:testGenerateOrdersWithLoanStartAtBlockTimestampInvalidLoan() (gas: 458397) +TestCustodian:testGenerateOrdersWithLoanStartAtBlockTimestampInvalidLoan() (gas: 458394) TestCustodian:testGetBorrower() (gas: 78619) TestCustodian:testInvalidAction() (gas: 173196) TestCustodian:testInvalidActionRepayInActiveLoan() (gas: 130060) @@ -69,30 +69,30 @@ TestLenderEnforcer:testLERevertInvalidLoanTerms() (gas: 81062) TestLenderEnforcer:testLEValidLoanTerms() (gas: 72055) TestLenderEnforcer:testLEValidLoanTermsAnyBorrower() (gas: 72098) TestLenderEnforcer:testLEValidLoanTermsWithAdditionalTransfers() (gas: 73410) -TestLoanCombinations:testLoan20For721SimpleInterestDutchFixedRepay() (gas: 587270) -TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 594461) -TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 585469) -TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 575374) -TestNewLoan:testBuyNowPayLater() (gas: 2869309) +TestLoanCombinations:testLoan20For721SimpleInterestDutchFixedRepay() (gas: 587267) +TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 594458) +TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 585466) +TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 575371) +TestNewLoan:testBuyNowPayLater() (gas: 2869306) TestNewLoan:testInvalidSenderBNPL() (gas: 1613120) TestNewLoan:testInvalidUserDataHashBNPL() (gas: 1615699) TestNewLoan:testNewLoanAs1271ProxyAccountSender() (gas: 861457) -TestNewLoan:testNewLoanAs1271ProxyAccountThirdPartyFiller() (gas: 871145) -TestNewLoan:testNewLoanERC721CollateralDefaultTerms2() (gas: 424965) -TestNewLoan:testNewLoanRefinance() (gas: 577284) -TestNewLoan:testNewLoanViaOriginatorBorrowerApprovalAndLenderApproval() (gas: 325441) -TestNewLoan:testNewLoanViaOriginatorLenderApproval() (gas: 382057) -TestNewLoan:testSettleLoan() (gas: 636584) +TestNewLoan:testNewLoanAs1271ProxyAccountThirdPartyFiller() (gas: 871142) +TestNewLoan:testNewLoanERC721CollateralDefaultTerms2() (gas: 424962) +TestNewLoan:testNewLoanRefinance() (gas: 577281) +TestNewLoan:testNewLoanViaOriginatorBorrowerApprovalAndLenderApproval() (gas: 325414) +TestNewLoan:testNewLoanViaOriginatorLenderApproval() (gas: 382042) +TestNewLoan:testSettleLoan() (gas: 636581) TestPausableNonReentrant:testNotOwner() (gas: 21254) TestPausableNonReentrant:testPauseAndUnpause() (gas: 22555) TestPausableNonReentrant:testReentrancy() (gas: 15360) TestPausableNonReentrant:testUnpauseWhenNotPaused() (gas: 12582) -TestRepayLoan:testRepayLoanApprovedRepayer() (gas: 658789) -TestRepayLoan:testRepayLoanBase() (gas: 595065) -TestRepayLoan:testRepayLoanGenerateOrderNotSeaport() (gas: 434107) -TestRepayLoan:testRepayLoanInSettlement() (gas: 580650) -TestRepayLoan:testRepayLoanInvalidRepayer() (gas: 599079) -TestRepayLoan:testRepayLoanThatDoesNotExist() (gas: 853478) +TestRepayLoan:testRepayLoanApprovedRepayer() (gas: 658786) +TestRepayLoan:testRepayLoanBase() (gas: 595062) +TestRepayLoan:testRepayLoanGenerateOrderNotSeaport() (gas: 434104) +TestRepayLoan:testRepayLoanInSettlement() (gas: 580647) +TestRepayLoan:testRepayLoanInvalidRepayer() (gas: 599076) +TestRepayLoan:testRepayLoanThatDoesNotExist() (gas: 853475) TestSimpleInterestPricing:test_calculateInterest() (gas: 899536) TestSimpleInterestPricing:test_getPaymentConsideration() (gas: 946746) TestSimpleInterestPricing:test_getRefinanceConsideration() (gas: 937602) @@ -105,9 +105,9 @@ TestStarport:testCannotIssueSameLoanTwice() (gas: 359427) TestStarport:testCannotOriginateWhilePaused() (gas: 73501) TestStarport:testCannotSettleInvalidLoan() (gas: 74881) TestStarport:testCannotSettleUnlessValidCustodian() (gas: 70985) -TestStarport:testCaveatEnforcerRevert() (gas: 99214) -TestStarport:testDefaultFeeRake() (gas: 358092) -TestStarport:testDefaultFeeRakeExoticDebt() (gas: 368247) +TestStarport:testCaveatEnforcerRevert() (gas: 99211) +TestStarport:testDefaultFeeRake() (gas: 358089) +TestStarport:testDefaultFeeRakeExoticDebt() (gas: 368244) TestStarport:testExoticDebtWithCustomPricingAndRepayment() (gas: 1235383) TestStarport:testExoticDebtWithCustomPricingAndSettlement() (gas: 1690431) TestStarport:testExoticDebtWithNoCaveatsNotAsBorrower() (gas: 374504) @@ -123,8 +123,8 @@ TestStarport:testInvalidTransferLengthDebt() (gas: 173547) TestStarport:testInvalidateCaveatSalt() (gas: 33538) TestStarport:testNonDefaultCustodianCustodyCallFails() (gas: 261852) TestStarport:testNonDefaultCustodianCustodyCallSuccess() (gas: 288087) -TestStarport:testNonPayableFunctions() (gas: 112087) -TestStarport:testOverrideFeeRake() (gas: 354454) +TestStarport:testNonPayableFunctions() (gas: 112084) +TestStarport:testOverrideFeeRake() (gas: 354451) TestStarport:testPause() (gas: 18115) TestStarport:testRefinancePostRepaymentFails() (gas: 120853) TestStarport:testTokenNoCodeCollateral() (gas: 148380) @@ -134,13 +134,13 @@ TestStrategistOriginator:testEncodeWithAccountCounter() (gas: 12307) TestStrategistOriginator:testGetStrategistData() (gas: 1489933) TestStrategistOriginator:testIncrementCounterAsStrategist() (gas: 18676) TestStrategistOriginator:testIncrementCounterNotAuthorized() (gas: 13445) -TestStrategistOriginator:testInvalidCollateral() (gas: 209574) -TestStrategistOriginator:testInvalidDeadline() (gas: 215208) -TestStrategistOriginator:testInvalidDebt() (gas: 211256) -TestStrategistOriginator:testInvalidDebtAmountAskingMoreThanOffered() (gas: 211573) -TestStrategistOriginator:testInvalidDebtAmountOfferingZero() (gas: 211872) -TestStrategistOriginator:testInvalidDebtAmountRequestingZero() (gas: 211826) -TestStrategistOriginator:testInvalidDebtLength() (gas: 210368) -TestStrategistOriginator:testInvalidOffer() (gas: 424415) -TestStrategistOriginator:testInvalidSigner() (gas: 213725) +TestStrategistOriginator:testInvalidCollateral() (gas: 209562) +TestStrategistOriginator:testInvalidDeadline() (gas: 215196) +TestStrategistOriginator:testInvalidDebt() (gas: 211244) +TestStrategistOriginator:testInvalidDebtAmountAskingMoreThanOffered() (gas: 211561) +TestStrategistOriginator:testInvalidDebtAmountOfferingZero() (gas: 211860) +TestStrategistOriginator:testInvalidDebtAmountRequestingZero() (gas: 211814) +TestStrategistOriginator:testInvalidDebtLength() (gas: 210356) +TestStrategistOriginator:testInvalidOffer() (gas: 424400) +TestStrategistOriginator:testInvalidSigner() (gas: 213713) TestStrategistOriginator:testSetStrategist() (gas: 17796) \ No newline at end of file diff --git a/README.md b/README.md index 09e215ae..054b2e58 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ ## ✨ Starport + +### License + +[BUSL-1.1](LICENSE) Copyright 2023 Astaria Labs, Inc. diff --git a/src/BNPLHelper.sol b/src/BNPLHelper.sol index 53b4bddc..c34e6d4d 100644 --- a/src/BNPLHelper.sol +++ b/src/BNPLHelper.sol @@ -1,20 +1,51 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; +import {Starport} from "starport-core/Starport.sol"; +import {CaveatEnforcer} from "starport-core/enforcers/CaveatEnforcer.sol"; +import {AdditionalTransfer} from "starport-core/lib/StarportLib.sol"; + +import {Seaport} from "seaport/contracts/Seaport.sol"; import { - OfferItem, - SpentItem, - ConsiderationItem, AdvancedOrder, - OrderParameters, + ConsiderationItem, CriteriaResolver, + Fulfillment, ItemType, - Fulfillment + OfferItem, + OrderParameters, + SpentItem } from "seaport-types/src/lib/ConsiderationStructs.sol"; -import {AdditionalTransfer} from "starport-core/lib/StarportLib.sol"; -import {Seaport} from "seaport/contracts/Seaport.sol"; -import {Starport} from "./Starport.sol"; -import {CaveatEnforcer} from "./enforcers/CaveatEnforcer.sol"; +/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ +/* INTERFACES */ +/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ interface IVault { function flashLoan( @@ -39,9 +70,30 @@ interface ERC20 { } contract BNPLHelper is IFlashLoanRecipient { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CUSTOM ERRORS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + error DoNotSendETH(); + error InvalidUserDataProvided(); + error SenderNotVault(); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTANTS AND IMMUTABLES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + address private constant vault = address(0xBA12222222228d8Ba445958a75a0704d566BF2C8); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STORAGE */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + bytes32 private activeUserDataHash; + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STRUCTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + struct Execution { address lm; address seaport; @@ -54,10 +106,6 @@ contract BNPLHelper is IFlashLoanRecipient { Fulfillment[] fulfillments; } - error SenderNotVault(); - error DoNotSendETH(); - error InvalidUserDataProvided(); - function makeFlashLoan(address[] calldata tokens, uint256[] calldata amounts, bytes calldata userData) external { activeUserDataHash = keccak256(userData); @@ -65,7 +113,7 @@ contract BNPLHelper is IFlashLoanRecipient { } function receiveFlashLoan( - address[] calldata tokens, // are all erc20s + address[] calldata tokens, // Are all ERC-20s uint256[] calldata amounts, uint256[] calldata feeAmounts, bytes calldata userData @@ -80,7 +128,8 @@ contract BNPLHelper is IFlashLoanRecipient { delete activeUserDataHash; Execution memory execution = abi.decode(userData, (Execution)); - //approve seaport + + // Approve seaport for (uint256 i = 0; i < tokens.length;) { ERC20(tokens[i]).transfer(execution.borrower, amounts[i]); unchecked { diff --git a/src/Custodian.sol b/src/Custodian.sol index 97c4e67c..bfb21c94 100644 --- a/src/Custodian.sol +++ b/src/Custodian.sol @@ -1,85 +1,122 @@ // SPDX-License-Identifier: BUSL-1.1 -/** - * ,--, - * ,---.'| - * ,----.. ,---, ,-. | | : - * / / \ ,--.' | ,--, ,--/ /| : : | ,---, - * | : :| | : ,--.'| ,---, .---. ,---. __ ,-.,--. :/ | | ' : ,---.'| - * . | ;. /: : : | |, ,-+-. / | /. ./| ' ,'\ ,' ,'/ /|: : ' / .--.--. ; ; ' | | : .--.--. - * . ; /--` : | |,--. ,--.--. `--'_ ,--.'|' | .-'-. ' | / / |' | |' || ' / / / ' ' | |__ ,--.--. : : : / / ' - * ; | ; | : ' | / \ ,' ,'| | | ,"' | /___/ \: |. ; ,. :| | ,'' | : | : /`./ | | :.'| / \ : |,-.| : /`./ - * | : | | | /' :.--. .-. | ' | | | | / | | .-'.. ' ' .' | |: :' : / | | \| : ;_ ' : ;.--. .-. | | : ' || : ;_ - * . | '___ ' : | | | \__\/: . . | | : | | | | |/___/ \: '' | .; :| | ' ' : |. \\ \ `. | | ./ \__\/: . . | | / : \ \ `. - * ' ; : .'|| | ' | : ," .--.; | ' : |__ | | | |/ . \ ' .\ | : |; : | | | ' \ \`----. \ ; : ; ," .--.; | ' : |: | `----. \ - * ' | '/ :| : :_:,'/ / ,. | | | '.'|| | |--' \ \ ' \ | \ \ / | , ; ' : |--'/ /`--' / | ,/ / / ,. | | | '/ : / /`--' / - * | : / | | ,' ; : .' \; : ;| |/ \ \ |--" `----' ---' ; |,' '--'. / '---' ; : .' \| : |'--'. / - * \ \ .' `--'' | , .-./| , / '---' \ \ | '--' `--'---' | , .-.// \ / `--'---' - * `---` `--`---' ---`-' '---" `--`---' `-'----' - * - * Chainworks Labs - */ +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; -import {ERC721} from "solady/src/tokens/ERC721.sol"; -import {ERC20} from "solady/src/tokens/ERC20.sol"; -import {ERC1155} from "solady/src/tokens/ERC1155.sol"; +import {Starport} from "starport-core/Starport.sol"; +import {Pricing} from "starport-core/pricing/Pricing.sol"; +import {Settlement} from "starport-core/settlement/Settlement.sol"; +import {Status} from "starport-core/status/Status.sol"; +import {StarportLib, Actions} from "starport-core/lib/StarportLib.sol"; -import {ItemType, Schema, SpentItem, ReceivedItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; import {ContractOffererInterface} from "seaport-types/src/interfaces/ContractOffererInterface.sol"; - +import {ItemType, Schema, SpentItem, ReceivedItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; +import {ERC20} from "solady/src/tokens/ERC20.sol"; +import {ERC721} from "solady/src/tokens/ERC721.sol"; +import {ERC1155} from "solady/src/tokens/ERC1155.sol"; import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; -import {Status} from "./status/Status.sol"; -import {Settlement} from "./settlement/Settlement.sol"; -import {Pricing} from "./pricing/Pricing.sol"; -import {Starport} from "./Starport.sol"; -import {StarportLib, Actions} from "./lib/StarportLib.sol"; contract Custodian is ERC721, ContractOffererInterface { using {StarportLib.getId} for Starport.Loan; - Starport public immutable SP; - address public immutable seaport; - - event SeaportCompatibleContractDeployed(); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CUSTOM ERRORS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ error ImplementInChild(); error InvalidAction(); error InvalidFulfiller(); - error InvalidPostSettlement(); - error InvalidPostRepayment(); error InvalidLoan(); + error InvalidPostRepayment(); + error InvalidPostSettlement(); error InvalidRepayer(); error NotAuthorized(); - error NotSeaport(); error NotEnteredViaSeaport(); + error NotSeaport(); error NotStarport(); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EVENTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + event SeaportCompatibleContractDeployed(); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTANTS AND IMMUTABLES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + Starport public immutable SP; + address public immutable seaport; + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STRUCTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + struct Command { + Actions action; + Starport.Loan loan; + bytes extraData; + } + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTRUCTOR */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + constructor(Starport SP_, address seaport_) { seaport = seaport_; SP = SP_; + emit SeaportCompatibleContractDeployed(); } - struct Command { - Actions action; - Starport.Loan loan; - bytes extraData; + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* FUNCTION OVERRIDES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /** + * @dev The name of the ERC721 contract + * @return string The name of the contract + */ + function name() public pure override returns (string memory) { + return "Starport Custodian"; } /** - * @dev Fetches the borrower of the loan, first checks to see if we've minted the token for the loan - * @param loan Loan to get the borrower of - * @return address The address of the loan borrower(returns the ownerOf the token if any) defaults to loan.borrower + * @dev The symbol of the ERC721 contract + * @return string The symbol of the contract */ - function getBorrower(Starport.Loan memory loan) public view returns (address) { - uint256 loanId = loan.getId(); - return _exists(loanId) ? ownerOf(loanId) : loan.borrower; + function symbol() public pure override returns (string memory) { + return "SC"; } /** - * @dev erc721 tokenURI override - * @param loanId The id of the custody token/loan - * @return the string uri of the custody token/loan + * @dev ERC-721 tokenURI override + * @param loanId The id of the custody token/loan + * @return string URI of the custody token/loan */ function tokenURI(uint256 loanId) public view override returns (string memory) { if (!_exists(loanId)) { @@ -90,9 +127,8 @@ contract Custodian is ERC721, ContractOffererInterface { /** * @dev Helper to determine if an interface is supported by this contract - * - * @param interfaceId The interface to check - * @return bool return true if the interface is supported + * @param interfaceId The interface to check + * @return bool Returns true if the interface is supported */ function supportsInterface(bytes4 interfaceId) public @@ -105,49 +141,22 @@ contract Custodian is ERC721, ContractOffererInterface { } /** - * @dev The name of the ERC721 contract - * - * @return string The name of the contract - */ - function name() public pure override returns (string memory) { - return "Starport Custodian"; - } - - /** - * @dev The symbol of the ERC721 contract - * - * @return string The symbol of the contract - */ - function symbol() public pure override returns (string memory) { - return "SC"; - } - - //MODIFIERS - /** - * @dev only allows Starport to execute the function + * @dev onERC1155Received handler, if we are able to increment the counter + * in seaport that means we have not entered into seaport we dont add for + * ERC-721 as they are able to ignore the on handler call as apart of the spec + * revert with NotEnteredViaSeaport() */ - modifier onlyStarport() { - if (msg.sender != address(SP)) { - revert NotStarport(); - } - _; + function onERC1155Received(address, address, uint256, uint256, bytes calldata) public virtual returns (bytes4) { + return this.onERC1155Received.selector; } - /** - * @dev only allows seaport to execute the function - */ - modifier onlySeaport() { - if (msg.sender != address(seaport)) { - revert NotSeaport(); - } - _; - } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EXTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ - //EXTERNAL FUNCTIONS /** * @dev Mints a custody token for a loan. - * - * @param loan The loan to mint a custody token for + * @param loan The loan to mint a custody token for */ function mint(Starport.Loan calldata loan) external { bytes memory encodedLoan = abi.encode(loan); @@ -155,16 +164,14 @@ contract Custodian is ERC721, ContractOffererInterface { if (loan.custodian != address(this) || !SP.active(loanId)) { revert InvalidLoan(); } - _safeMint(loan.borrower, loanId, encodedLoan); } + /** * @dev Mints a custody token for a loan. - * - * @param loan The loan to mint a custody token for - * @param approvedTo The address with pre approvals set + * @param loan The loan to mint a custody token for + * @param approvedTo The address with pre approvals set */ - function mintWithApprovalSet(Starport.Loan calldata loan, address approvedTo) external { bytes memory encodedLoan = abi.encode(loan); uint256 loanId = uint256(keccak256(encodedLoan)); @@ -179,14 +186,13 @@ 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. + * @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, @@ -199,13 +205,12 @@ contract Custodian is ERC721, ContractOffererInterface { } /** - * @dev Generates the order for this contract offerer. - * - * @param fulfiller The address of the contract fulfiller. - * @param maximumSpent The maximum amount of items to be spent by the order. - * @param context The context of the order. - * @return offer The items spent by the order. - * @return consideration The items received by the order. + * @dev Generates the order for this contract offerer + * @param fulfiller The address of the contract fulfiller + * @param maximumSpent The maximum amount of items to be spent by the order + * @param context The context of the order + * @return offer The items spent by the order + * @return consideration The items received by the order */ function generateOrder( address fulfiller, @@ -255,48 +260,57 @@ contract Custodian is ERC721, ContractOffererInterface { /** * @dev If any additional state updates are needed when taking custody of a loan - * - * @param loan The loan that was just placed into custody - * @return selector The function selector of the custody method + * @param loan The loan that was just placed into custody + * @return selector The function selector of the custody method */ function custody(Starport.Loan memory loan) external virtual onlyStarport returns (bytes4 selector) { revert ImplementInChild(); } /** - * @dev returns metadata on how to interact with the offerer contract - * - * @return string the name of the contract - * @return schemas an array of supported schemas + * @dev Returns metadata on how to interact with the offerer contract + * @return string The name of the contract + * @return schemas An array of supported schemas */ function getSeaportMetadata() external pure returns (string memory, Schema[] memory schemas) { - //adhere to sip data, how to encode the context and what it is - //TODO: add in the context for the loan - //you need to parse SP Open events for the loan and abi encode it + // Adhere to SIP data, how to encode the context and what it is + // TODO: add in the context for the loan + // you need to parse SP Open events for the loan and ABI encode it schemas = new Schema[](1); schemas[0] = Schema(8, ""); return ("Loans", schemas); } - // PUBLIC FUNCTIONS + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* PUBLIC FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** - * @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 Fetches the borrower of the loan, first checks to see if we've minted the token for the loan + * @param loan Loan to get the borrower of + * @return address The address of the loan borrower(returns the ownerOf the token if any) defaults to loan.borrower + */ + function getBorrower(Starport.Loan memory loan) public view returns (address) { + uint256 loanId = loan.getId(); + return _exists(loanId) ? ownerOf(loanId) : loan.borrower; + } + + /** + * @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. */ function previewOrder( address caller, address fulfiller, SpentItem[] calldata minimumReceived, SpentItem[] calldata maximumSpent, - bytes calldata context // encoded based on the schemaID + bytes calldata context // Encoded based on the schemaID ) public view returns (SpentItem[] memory offer, ReceivedItem[] memory consideration) { (Command memory close) = abi.decode(context, (Command)); Starport.Loan memory loan = close.loan; @@ -328,21 +342,12 @@ contract Custodian is ERC721, ContractOffererInterface { } } - /** - * @dev onERC1155Received handler - * if we are able to increment the counter in seaport that means we have not entered into seaport - * we dont add for 721 as they are able to ignore the on handler call as apart of the spec - * revert with NotEnteredViaSeaport() - */ - function onERC1155Received(address, address, uint256, uint256, bytes calldata) public virtual returns (bytes4) { - return this.onERC1155Received.selector; - } - - //INTERNAL FUNCTIONS + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* INTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** - * @dev enables the collateral deposited to be spent via seaport - * + * @dev Enables the collateral deposited to be spent via seaport * @param offer The item to make available to seaport */ function _enableAssetWithSeaport(SpentItem memory offer) internal { @@ -357,8 +362,7 @@ contract Custodian is ERC721, ContractOffererInterface { } /** - * @dev set's approvals for the collateral deposited to be spent via seaport - * + * @dev Sets approvals for the collateral deposited to be spent via seaport * @param loan The loan being settled */ function _setOfferApprovalsWithSeaport(Starport.Loan memory loan) internal { @@ -370,13 +374,11 @@ contract Custodian is ERC721, ContractOffererInterface { /** * @dev transfers out the collateral to the handler address - * - * @param offer The item to send out of the Custodian - * @param authorized The address handling the asset further + * @param offer The item to send out of the Custodian + * @param authorized The address handling the asset further */ - function _transferCollateralAuthorized(SpentItem memory offer, address authorized) internal { - //approve consideration based on item type + // Approve consideration based on item type if (offer.itemType == ItemType.ERC721) { ERC721(offer.token).transferFrom(address(this), authorized, offer.identifier); } else if (offer.itemType == ItemType.ERC1155) { @@ -388,9 +390,8 @@ contract Custodian is ERC721, ContractOffererInterface { /** * @dev transfers out the collateral of SpentItem to the handler address - * - * @param offer The SpentItem array to send out of the Custodian - * @param authorized The address handling the asset further + * @param offer The SpentItem array to send out of the Custodian + * @param authorized The address handling the asset further */ function _moveCollateralToAuthorized(SpentItem[] memory offer, address authorized) internal { for (uint256 i = 0; i < offer.length; i++) { @@ -400,9 +401,8 @@ 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 + * @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); @@ -414,11 +414,9 @@ 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 + * @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(loan, fulfiller) != Settlement.postRepayment.selector) { @@ -429,8 +427,7 @@ contract Custodian is ERC721, ContractOffererInterface { /** * @dev settle the loan with the LoanManager - * - * @param loan The the loan to settle + * @param loan The the loan to settle */ function _settleLoan(Starport.Loan memory loan) internal virtual { _beforeSettleLoanHook(loan); @@ -442,53 +439,72 @@ contract Custodian is ERC721, ContractOffererInterface { _afterSettleLoanHook(loan); } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* HOOKS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /** * @dev hook to call before the approvals are set - * - * @param loan The loan being settled + * @param loan The loan being settled */ function _beforeApprovalsSetHook(Starport.Loan memory loan) internal virtual {} /** - * @dev hook to call before the loan get settlement call - * - * @param loan The loan being settled + * @dev Hook to call before the loan get settlement call + * @param loan The loan being settled */ function _beforeGetSettlementConsideration(Starport.Loan memory loan) internal virtual {} /** - * @dev hook to call after the loan get settlement call - * - * - * @param loan The loan being settled + * @dev Hook to call after the loan get settlement call + * @param loan The loan being settled */ function _afterGetSettlementConsideration(Starport.Loan memory loan) internal virtual {} /** - * @dev hook to call before the the loan settlement handler execute call - * - * @param loan The loan being settled + * @dev Hook to call before the the loan settlement handler execute call + * @param loan The loan being settled */ function _beforeSettlementHandlerHook(Starport.Loan memory loan) internal virtual {} /** - * @dev hook to call after the the loan settlement handler execute call - * - * - * @param loan The loan being settled + * @dev Hook to call after the the loan settlement handler execute call + * @param loan The loan being settled */ function _afterSettlementHandlerHook(Starport.Loan memory loan) internal virtual {} /** - * @dev hook to call before the loan is settled with the LM - * - * @param loan The loan being settled + * @dev Hook to call before the loan is settled with the LM + * @param loan The loan being settled */ function _beforeSettleLoanHook(Starport.Loan memory loan) internal virtual {} /** - * @dev hook to call after the loan is settled with the LM - * - * @param loan The loan being settled + * @dev Hook to call after the loan is settled with the LM + * @param loan The loan being settled */ function _afterSettleLoanHook(Starport.Loan memory loan) internal virtual {} + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* MODIFIERS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /** + * @dev only allows Starport to execute the function + */ + modifier onlyStarport() { + if (msg.sender != address(SP)) { + revert NotStarport(); + } + _; + } + + /** + * @dev only allows seaport to execute the function + */ + modifier onlySeaport() { + if (msg.sender != address(seaport)) { + revert NotSeaport(); + } + _; + } } diff --git a/src/Starport.sol b/src/Starport.sol index dd3e07ef..51dd67ad 100644 --- a/src/Starport.sol +++ b/src/Starport.sol @@ -1,69 +1,125 @@ // SPDX-License-Identifier: BUSL-1.1 -/** - * ,--, - * ,---.'| - * ,----.. ,---, ,-. | | : - * / / \ ,--.' | ,--, ,--/ /| : : | ,---, - * | : :| | : ,--.'| ,---, .---. ,---. __ ,-.,--. :/ | | ' : ,---.'| - * . | ;. /: : : | |, ,-+-. / | /. ./| ' ,'\ ,' ,'/ /|: : ' / .--.--. ; ; ' | | : .--.--. - * . ; /--` : | |,--. ,--.--. `--'_ ,--.'|' | .-'-. ' | / / |' | |' || ' / / / ' ' | |__ ,--.--. : : : / / ' - * ; | ; | : ' | / \ ,' ,'| | | ,"' | /___/ \: |. ; ,. :| | ,'' | : | : /`./ | | :.'| / \ : |,-.| : /`./ - * | : | | | /' :.--. .-. | ' | | | | / | | .-'.. ' ' .' | |: :' : / | | \| : ;_ ' : ;.--. .-. | | : ' || : ;_ - * . | '___ ' : | | | \__\/: . . | | : | | | | |/___/ \: '' | .; :| | ' ' : |. \\ \ `. | | ./ \__\/: . . | | / : \ \ `. - * ' ; : .'|| | ' | : ," .--.; | ' : |__ | | | |/ . \ ' .\ | : |; : | | | ' \ \`----. \ ; : ; ," .--.; | ' : |: | `----. \ - * ' | '/ :| : :_:,'/ / ,. | | | '.'|| | |--' \ \ ' \ | \ \ / | , ; ' : |--'/ /`--' / | ,/ / / ,. | | | '/ : / /`--' / - * | : / | | ,' ; : .' \; : ;| |/ \ \ |--" `----' ---' ; |,' '--'. / '---' ; : .' \| : |'--'. / - * \ \ .' `--'' | , .-./| , / '---' \ \ | '--' `--'---' | , .-.// \ / `--'---' - * `---` `--`---' ---`-' '---" `--`---' `-'----' - * - * Chainworks Labs - */ +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; -import {CaveatEnforcer} from "./enforcers/CaveatEnforcer.sol"; -import {Custodian} from "./Custodian.sol"; +import {CaveatEnforcer} from "starport-core/enforcers/CaveatEnforcer.sol"; +import {Custodian} from "starport-core/Custodian.sol"; +import {PausableNonReentrant} from "starport-core/lib/PausableNonReentrant.sol"; +import {Pricing} from "starport-core/pricing/Pricing.sol"; +import {Settlement} from "starport-core/settlement/Settlement.sol"; +import {StarportLib, AdditionalTransfer} from "starport-core/lib/StarportLib.sol"; + +import {SpentItem, ItemType} from "seaport-types/src/lib/ConsiderationStructs.sol"; import {ERC20} from "solady/src/tokens/ERC20.sol"; import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; -import {PausableNonReentrant} from "./lib/PausableNonReentrant.sol"; -import {Pricing} from "./pricing/Pricing.sol"; import {SafeTransferLib} from "solady/src/utils/SafeTransferLib.sol"; -import {Settlement} from "./settlement/Settlement.sol"; import {SignatureCheckerLib} from "solady/src/utils/SignatureCheckerLib.sol"; -import {SpentItem, ItemType} from "seaport-types/src/lib/ConsiderationStructs.sol"; -import {StarportLib, AdditionalTransfer} from "./lib/StarportLib.sol"; contract Starport is PausableNonReentrant { using FixedPointMathLib for uint256; using {StarportLib.getId} for Starport.Loan; using {StarportLib.validateSalt} for mapping(address => mapping(bytes32 => bool)); - enum ApprovalType { - NOTHING, - BORROWER, - LENDER - } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CUSTOM ERRORS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + error AdditionalTransferError(); + error CannotTransferLoans(); + error CaveatDeadlineExpired(); + error InvalidCaveatSigner(); + error InvalidCustodian(); + error InvalidLoan(); + error InvalidPostRepayment(); + error InvalidRefinance(); + error LoanExists(); + error MalformedRefinance(); + error NotLoanCustodian(); + error UnauthorizedAdditionalTransferIncluded(); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EVENTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + event ApprovalSet(address indexed owner, address indexed spender, uint8 approvalType); + event CaveatFilled(address owner, bytes32 hash, bytes32 salt); + event CaveatNonceIncremented(address owner, uint256 newNonce); + event CaveatSaltInvalidated(address owner, bytes32 salt); + event Close(uint256 loanId); + event FeeDataUpdated(address feeTo, uint88 defaultFeeRake); + event FeeOverrideUpdated(address token, uint88 overrideValue, bool enabled); + event Open(uint256 loanId, Starport.Loan loan); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTANTS AND IMMUTABLES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ uint256 public constant LOAN_INACTIVE_FLAG = 0x0; uint256 public constant LOAN_ACTIVE_FLAG = 0x1; + bytes32 private constant _INVALID_LOAN = 0x045f33d100000000000000000000000000000000000000000000000000000000; + bytes32 private constant _LOAN_EXISTS = 0x14ec57fc00000000000000000000000000000000000000000000000000000000; + + address public immutable defaultCustodian; + bytes32 public immutable DEFAULT_CUSTODIAN_CODE_HASH; + + bytes32 internal immutable _DOMAIN_SEPARATOR; + + // Define the EIP712 domain and typehash constants for generating signatures + bytes32 public constant EIP_DOMAIN = + keccak256("EIP712Domain(string version,uint256 chainId,address verifyingContract)"); + string public constant VERSION = "0"; + bytes32 public constant INTENT_ORIGINATION_TYPEHASH = keccak256( + "Origination(address account,uint256 accountNonce,bool singleUse,bytes32 salt,uint256 deadline,bytes32 caveatHash" + ); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STRUCTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + struct Terms { - address status; //the address of the status module - bytes statusData; //bytes encoded hook data - address pricing; //the address o the pricing module - bytes pricingData; //bytes encoded pricing data - address settlement; //the address of the handler module - bytes settlementData; //bytes encoded handler data + address status; // the address of the status module + bytes statusData; // bytes encoded hook data + address pricing; // the address of the pricing module + bytes pricingData; // bytes encoded pricing data + address settlement; // the address of the handler module + bytes settlementData; // bytes encoded handler data } struct Loan { - uint256 start; //start of the loan - address custodian; //where the collateral is being held - address borrower; //the borrower - address issuer; //the capital issuer/lender - address originator; //who originated the loan - SpentItem[] collateral; //array of collateral - SpentItem[] debt; //array of debt - Terms terms; //the actionable terms of the loan + uint256 start; // start of the loan + address custodian; // where the collateral is being held + address borrower; // the borrower + address issuer; // the capital issuer/lender + address originator; // who originated the loan + SpentItem[] collateral; // array of collateral + SpentItem[] debt; // array of debt + Terms terms; // the actionable terms of the loan } struct Fee { @@ -71,48 +127,32 @@ contract Starport is PausableNonReentrant { uint88 amount; } - bytes32 internal immutable _DOMAIN_SEPARATOR; + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* ENUMS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ - address public immutable defaultCustodian; - bytes32 public immutable DEFAULT_CUSTODIAN_CODE_HASH; + enum ApprovalType { + NOTHING, + BORROWER, + LENDER + } - // Define the EIP712 domain and typehash constants for generating signatures - bytes32 public constant EIP_DOMAIN = - keccak256("EIP712Domain(string version,uint256 chainId,address verifyingContract)"); - string public constant VERSION = "0"; - bytes32 public constant INTENT_ORIGINATION_TYPEHASH = keccak256( - "Origination(address account,uint256 accountNonce,bool singleUse,bytes32 salt,uint256 deadline,bytes32 caveatHash" - ); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STORAGE */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ address public feeTo; uint88 public defaultFeeRake; + + mapping(address => Fee) public feeOverrides; mapping(address => mapping(address => ApprovalType)) public approvals; mapping(address => mapping(bytes32 => bool)) public invalidSalts; - mapping(uint256 => uint256) public loanState; mapping(address => uint256) public caveatNonces; - mapping(address => Fee) public feeOverrides; + mapping(uint256 => uint256) public loanState; - event Close(uint256 loanId); - event Open(uint256 loanId, Starport.Loan loan); - event CaveatNonceIncremented(address owner, uint256 newNonce); - event CaveatSaltInvalidated(address owner, bytes32 salt); - event CaveatFilled(address owner, bytes32 hash, bytes32 salt); - event FeeDataUpdated(address feeTo, uint88 defaultFeeRake); - event FeeOverrideUpdated(address token, uint88 overrideValue, bool enabled); - event ApprovalSet(address indexed owner, address indexed spender, uint8 approvalType); - - error InvalidRefinance(); - error InvalidCustodian(); - error InvalidLoan(); - error CannotTransferLoans(); - error AdditionalTransferError(); - error LoanExists(); - error NotLoanCustodian(); - error UnauthorizedAdditionalTransferIncluded(); - error InvalidCaveatSigner(); - error CaveatDeadlineExpired(); - error MalformedRefinance(); - error InvalidPostRepayment(); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTRUCTOR */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ constructor(address seaport_) { address custodian = address(new Custodian(this, seaport_)); @@ -127,33 +167,38 @@ contract Starport is PausableNonReentrant { _initializeOwner(msg.sender); } - /* - * @dev set's approval to originate loans without having to check caveats - * @param who The address of who is being approved - * @param approvalType The type of approval (Borrower, Lender) (cant be both) - */ + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EXTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /** + * @dev Sets approval to originate loans without having to check caveats + * @param who The address of who is being approved + * @param approvalType The type of approval (Borrower, Lender) (cant be both) + */ function setOriginateApproval(address who, ApprovalType approvalType) external { approvals[msg.sender][who] = approvalType; emit ApprovalSet(msg.sender, who, uint8(approvalType)); } - /* - * @dev loan origination method, new loan data is passed in and validated before being issued - * @param additionalTransfers Additional transfers to be made after the loan is issued - * @param borrowerCaveat The borrower caveat to be validated - * @param lenderCaveat The lender caveat to be validated - * @param loan The loan to be issued - */ + /** + * @dev The loan origination method, new loan data is passed in and validated before being issued + * @param additionalTransfers Additional transfers to be made after the loan is issued + * @param borrowerCaveat The borrower caveat to be validated + * @param lenderCaveat The lender caveat to be validated + * @param loan The loan to be issued + */ function originate( AdditionalTransfer[] calldata additionalTransfers, CaveatEnforcer.SignedCaveats calldata borrowerCaveat, CaveatEnforcer.SignedCaveats calldata lenderCaveat, Starport.Loan memory loan ) external payable pausableNonReentrant { - //cache the addresses + // Cache the addresses address borrower = loan.borrower; address issuer = loan.issuer; address feeRecipient = feeTo; + if (msg.sender != borrower && approvals[borrower][msg.sender] != ApprovalType.BORROWER) { _validateAndEnforceCaveats(borrowerCaveat, borrower, additionalTransfers, loan); } @@ -179,19 +224,18 @@ contract Starport is PausableNonReentrant { StarportLib.transferAdditionalTransfersCalldata(additionalTransfers); } - //sets originator and start time + // Sets originator and start time _issueLoan(loan); _callCustody(loan); } - /* - * @dev refinances an existing loan with new pricing data - * its the only thing that can be changed - * @param lender The new lender - * @param lenderCaveat The lender caveat to be validated - * @param loan The loan to be issued - * @param newPricingData The new pricing data - */ + /** + * @dev Refinances an existing loan with new pricing data, its the only thing that can be changed + * @param lender The new lender + * @param lenderCaveat The lender caveat to be validated + * @param loan The loan to be issued + * @param pricingData The new pricing data + */ function refinance( address lender, CaveatEnforcer.SignedCaveats calldata lenderCaveat, @@ -230,22 +274,71 @@ contract Starport is PausableNonReentrant { StarportLib.transferAdditionalTransfers(additionalTransfers); } - //sets originator and start time + // Sets originator and start time _issueLoan(loan); } /** - * @dev settle the loan with the LoanManager - * - * @param loan The the loan that is settled - * @param fulfiller The address executing the settle + * @dev Helper to settle a loan + * guarded to ensure only the loan.custodian can call it + * @param loan The entire loan struct */ - function _postRepaymentExecute(Starport.Loan memory loan, address fulfiller) internal virtual { - if (Settlement(loan.terms.settlement).postRepayment(loan, fulfiller) != Settlement.postRepayment.selector) { - revert InvalidPostRepayment(); + function settle(Loan memory loan) external { + if (msg.sender != loan.custodian) { + revert NotLoanCustodian(); } + _settle(loan); + } + + /** + * @dev Increments caveat nonce for sender and emits event + */ + function incrementCaveatNonce() external { + uint256 newNonce = caveatNonces[msg.sender] + uint256(blockhash(block.number - 1) << 0x80); + caveatNonces[msg.sender] = newNonce; + emit CaveatNonceIncremented(msg.sender, newNonce); + } + + /** + * @dev Invalidates a caveat salt + * @param salt The salt to invalidate + */ + function invalidateCaveatSalt(bytes32 salt) external { + invalidSalts.validateSalt(msg.sender, salt); + emit CaveatSaltInvalidated(msg.sender, salt); + } + + /** + * @dev Sets the default fee data, only owner can call + * @param feeTo_ The feeToAddress + * @param defaultFeeRake_ The default fee rake in WAD denomination(1e17 = 10%) + */ + function setFeeData(address feeTo_, uint88 defaultFeeRake_) external onlyOwner { + feeTo = feeTo_; + defaultFeeRake = defaultFeeRake_; + emit FeeDataUpdated(feeTo_, defaultFeeRake_); } + /** + * @dev Sets fee overrides for specific tokens, only owner can call + * @param token The token to override + * @param overrideValue The new value in WAD denomination to override(1e17 = 10%) + * @param enabled Whether or not the override is enabled + */ + function setFeeOverride(address token, uint88 overrideValue, bool enabled) external onlyOwner { + feeOverrides[token] = Fee({enabled: enabled, amount: overrideValue}); + emit FeeOverrideUpdated(token, overrideValue, enabled); + } + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* PUBLIC FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /** + * @dev Refinances an existing loan with new pricing data, its the only thing that can be changed + * @param considerationPayment the payment consideration + * @param carryPayment The loan to be issued + */ function applyRefinanceConsiderationToLoan(SpentItem[] memory considerationPayment, SpentItem[] memory carryPayment) public pure @@ -287,9 +380,78 @@ contract Starport is PausableNonReentrant { } /** - * @dev internal method to call the custody selector of the custodian if it does not share + * @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 salt The salt to use + * @param deadline The deadline of the caveat + * @param caveats The caveats to hash + * @return bytes32 The hash of the caveat + */ + function hashCaveatWithSaltAndNonce( + address account, + bool singleUse, + bytes32 salt, + uint256 deadline, + CaveatEnforcer.Caveat[] calldata caveats + ) public view virtual returns (bytes32) { + return keccak256( + abi.encodePacked( + bytes1(0x19), + bytes1(0x01), + _DOMAIN_SEPARATOR, + keccak256( + abi.encode( + INTENT_ORIGINATION_TYPEHASH, + account, + caveatNonces[account], + singleUse, + salt, + deadline, + keccak256(abi.encode(caveats)) + ) + ) + ) + ); + } + + /** + * @dev Helper to check if a loan is active + * @param loanId The id of the loan + * @return bool True if the loan is active + */ + function active(uint256 loanId) public view returns (bool) { + return loanState[loanId] == LOAN_ACTIVE_FLAG; + } + + /** + * @dev Helper to check if a loan is inactive + * @param loanId The id of the loan + * @return bool True if the loan is inactive + */ + function inactive(uint256 loanId) public view returns (bool) { + return loanState[loanId] == LOAN_INACTIVE_FLAG; + } + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* INTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /** + * @dev Settle the loan with the LoanManager + * @param loan The the loan that is settled + * @param fulfiller The address executing the settle + */ + function _postRepaymentExecute(Starport.Loan memory loan, address fulfiller) internal virtual { + if (Settlement(loan.terms.settlement).postRepayment(loan, fulfiller) != Settlement.postRepayment.selector) { + revert InvalidPostRepayment(); + } + } + + /** + * @dev Internal method to call the custody selector of the custodian if it does not share * the same codehash as the default custodian - * @param loan The loan being placed into custody + * @param loan The loan being placed into custody */ function _callCustody(Starport.Loan memory loan) internal { address custodian = loan.custodian; @@ -306,6 +468,12 @@ contract Starport is PausableNonReentrant { } } + /** + * @dev Internal method to validate additional transfers + * @param lender The lender of the loan + * @param fulfiller The fulfiller of the loan + * @param additionalTransfers The additional transfers to validate + */ function _validateAdditionalTransfersRefinance( address lender, address fulfiller, @@ -322,6 +490,13 @@ contract Starport is PausableNonReentrant { } } + /** + * @dev Internal method to validate additional transfers + * @param borrower The borrower of the loan + * @param lender The lender of the loan + * @param fulfiller The fulfiller of the loan + * @param additionalTransfers The additional transfers to validate + */ function _validateAdditionalTransfersOriginate( address borrower, address lender, @@ -340,6 +515,13 @@ contract Starport is PausableNonReentrant { } } + /** + * @dev Internal method to validate and enforce caveats + * @param signedCaveats The signed caveats to validate + * @param validator The validator of the caveats + * @param additionalTransfers The additional transfers to validate + * @param loan The loan to validate + */ function _validateAndEnforceCaveats( CaveatEnforcer.SignedCaveats calldata signedCaveats, address validator, @@ -372,77 +554,10 @@ contract Starport is PausableNonReentrant { } } - function hashCaveatWithSaltAndNonce( - address account, - bool singleUse, - bytes32 salt, - uint256 deadline, - CaveatEnforcer.Caveat[] calldata caveats - ) public view virtual returns (bytes32) { - return keccak256( - abi.encodePacked( - bytes1(0x19), - bytes1(0x01), - _DOMAIN_SEPARATOR, - keccak256( - abi.encode( - INTENT_ORIGINATION_TYPEHASH, - account, - caveatNonces[account], - singleUse, - salt, - deadline, - keccak256(abi.encode(caveats)) - ) - ) - ) - ); - } - - function incrementCaveatNonce() external { - uint256 newNonce = caveatNonces[msg.sender] + uint256(blockhash(block.number - 1) << 0x80); - caveatNonces[msg.sender] = newNonce; - emit CaveatNonceIncremented(msg.sender, newNonce); - } - - function invalidateCaveatSalt(bytes32 salt) external { - invalidSalts.validateSalt(msg.sender, salt); - emit CaveatSaltInvalidated(msg.sender, salt); - } - - /** - * @dev helper to check if a loan is active - * @param loanId The id of the loan - * @return True if the loan is active - */ - function active(uint256 loanId) public view returns (bool) { - return loanState[loanId] == LOAN_ACTIVE_FLAG; - } - - /** - * @dev helper to check if a loan is inactive - * @param loanId The id of the loan - * @return True if the loan is inactive - */ - function inactive(uint256 loanId) public view returns (bool) { - return loanState[loanId] == LOAN_INACTIVE_FLAG; - } - /** - * @dev helper to check if a loan is initialized(ie. has never been opened) - * guarded to ensure only the loan.custodian can call it - * @param loan The entire loan struct + * @dev Internal helper to settle a loan + * @param loan The entire loan struct */ - function settle(Loan memory loan) external { - if (msg.sender != loan.custodian) { - revert NotLoanCustodian(); - } - _settle(loan); - } - - bytes32 private constant _INVALID_LOAN = 0x045f33d100000000000000000000000000000000000000000000000000000000; - bytes32 private constant _LOAN_EXISTS = 0x14ec57fc00000000000000000000000000000000000000000000000000000000; - function _settle(Loan memory loan) internal { uint256 loanId = loan.getId(); assembly { @@ -450,12 +565,11 @@ contract Starport is PausableNonReentrant { mstore(0x20, loanState.slot) // loanState[loanId] - let loc := keccak256(0x0, 0x40) // if (inactive(loanId)) { if iszero(sload(loc)) { - //revert InvalidLoan() + // revert InvalidLoan() mstore(0x0, _INVALID_LOAN) revert(0x0, 0x04) } @@ -467,34 +581,9 @@ contract Starport is PausableNonReentrant { } /** - * @dev set's the default fee Data - * only owner can call - * @param feeTo_ The feeToAddress - * @param defaultFeeRake_ the default fee rake in WAD denomination(1e17 = 10%) - */ - function setFeeData(address feeTo_, uint88 defaultFeeRake_) external onlyOwner { - feeTo = feeTo_; - defaultFeeRake = defaultFeeRake_; - emit FeeDataUpdated(feeTo_, defaultFeeRake_); - } - - /** - * @dev set's fee override's for specific tokens - * only owner can call - * @param token The token to override - * @param overrideValue The new value in WAD denomination to override(1e17 = 10%) - * @param enabled Whether or not the override is enabled - */ - function setFeeOverride(address token, uint88 overrideValue, bool enabled) external onlyOwner { - feeOverrides[token] = Fee({enabled: enabled, amount: overrideValue}); - emit FeeOverrideUpdated(token, overrideValue, enabled); - } - - /** - * @dev set's fee override's for specific tokens - * only owner can call + * @dev Sets fee overrides for specific tokens, only owner can call * @param debt The debt to rake - * @return feeItems SpentItem[] of fee's + * @return feeItems SpentItem[] of fees */ function _feeRake(SpentItem[] memory debt) internal @@ -540,28 +629,24 @@ contract Starport is PausableNonReentrant { } /** - * @dev issues a LM token if needed - * only owner can call - * @param loan the loan to issue + * @dev Issues a LM token if needed, only owner can call + * @param loan The loan to issue */ function _issueLoan(Loan memory loan) internal { loan.start = block.timestamp; loan.originator = loan.originator != address(0) ? loan.originator : msg.sender; uint256 loanId = loan.getId(); - // if (active(loanId)) { - // revert LoanExists(); - // } - // + assembly { mstore(0x0, loanId) mstore(0x20, loanState.slot) - //loanState[loanId] + // loanState[loanId] let loc := keccak256(0x0, 0x40) // if (active(loanId)) if iszero(iszero(sload(loc))) { - //revert LoanExists() + // revert LoanExists() mstore(0x0, _LOAN_EXISTS) revert(0x0, 0x04) } diff --git a/src/enforcers/BorrowerEnforcer.sol b/src/enforcers/BorrowerEnforcer.sol index 15df3bb9..db01746d 100644 --- a/src/enforcers/BorrowerEnforcer.sol +++ b/src/enforcers/BorrowerEnforcer.sol @@ -1,18 +1,59 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; +import {Starport} from "starport-core/Starport.sol"; import {CaveatEnforcer} from "starport-core/enforcers/CaveatEnforcer.sol"; import {AdditionalTransfer} from "starport-core/lib/StarportLib.sol"; -import {Starport} from "starport-core/Starport.sol"; + import {ConsiderationInterface} from "seaport-types/src/interfaces/ConsiderationInterface.sol"; contract BorrowerEnforcer is CaveatEnforcer { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CUSTOM ERRORS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + error BorrowerOnlyEnforcer(); error InvalidLoanTerms(); error InvalidAdditionalTransfer(); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STRUCTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + struct Details { Starport.Loan loan; } + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* FUNCTION OVERRIDES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /** * @dev Enforces that the loan terms are identical except for the issuer * The issuer is allowed to be any address @@ -21,7 +62,6 @@ contract BorrowerEnforcer is CaveatEnforcer { * @param loan The loan terms * @param caveatData The borrowers encoded details */ - function validate( AdditionalTransfer[] calldata additionalTransfers, Starport.Loan calldata loan, diff --git a/src/enforcers/BorrowerEnforcerBNPL.sol b/src/enforcers/BorrowerEnforcerBNPL.sol index 8fb6fa69..26e3aff7 100644 --- a/src/enforcers/BorrowerEnforcerBNPL.sol +++ b/src/enforcers/BorrowerEnforcerBNPL.sol @@ -1,17 +1,52 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; +import {Starport} from "starport-core/Starport.sol"; import {CaveatEnforcer} from "starport-core/enforcers/CaveatEnforcer.sol"; import {AdditionalTransfer} from "starport-core/lib/StarportLib.sol"; -import {Starport} from "starport-core/Starport.sol"; + import {ConsiderationInterface} from "seaport-types/src/interfaces/ConsiderationInterface.sol"; contract BorrowerEnforcerBNPL is CaveatEnforcer { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CUSTOM ERRORS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + error BorrowerOnlyEnforcer(); error InvalidLoanTerms(); error InvalidAdditionalTransfer(); - error OrderInvalid(); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STRUCTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + struct Details { Starport.Loan loan; address seaport; @@ -19,6 +54,10 @@ contract BorrowerEnforcerBNPL is CaveatEnforcer { AdditionalTransfer additionalTransfer; } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* FUNCTION OVERRIDES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /** * @dev Enforces that the loan terms are identical except for the issuer * The issuer is allowed to be any address diff --git a/src/enforcers/CaveatEnforcer.sol b/src/enforcers/CaveatEnforcer.sol index 1af6e398..b030d903 100644 --- a/src/enforcers/CaveatEnforcer.sol +++ b/src/enforcers/CaveatEnforcer.sol @@ -1,9 +1,40 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; -import {AdditionalTransfer} from "starport-core/lib/StarportLib.sol"; import {Starport} from "starport-core/Starport.sol"; +import {AdditionalTransfer} from "starport-core/lib/StarportLib.sol"; abstract contract CaveatEnforcer { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STRUCTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + struct Caveat { address enforcer; bytes data; @@ -17,11 +48,15 @@ abstract contract CaveatEnforcer { bytes signature; } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* FUNCTION OVERRIDES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /** * @dev Enforces that the loan terms are identical except for the issuer - * @param solution The additional transfers to be made - * @param loan The loan terms - * @param caveatData The borrowers encoded details + * @param solution The additional transfers to be made + * @param loan The loan terms + * @param caveatData The borrowers encoded details */ function validate(AdditionalTransfer[] calldata solution, Starport.Loan calldata loan, bytes calldata caveatData) public diff --git a/src/enforcers/LenderEnforcer.sol b/src/enforcers/LenderEnforcer.sol index 677eb6a8..f50aa11b 100644 --- a/src/enforcers/LenderEnforcer.sol +++ b/src/enforcers/LenderEnforcer.sol @@ -1,14 +1,45 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; +import {Starport} from "starport-core/Starport.sol"; import {CaveatEnforcer} from "starport-core/enforcers/CaveatEnforcer.sol"; import {AdditionalTransfer} from "starport-core/lib/StarportLib.sol"; -import {Starport} from "starport-core/Starport.sol"; contract LenderEnforcer is CaveatEnforcer { error LenderOnlyEnforcer(); error InvalidLoanTerms(); error InvalidAdditionalTransfer(); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STRUCTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + struct Details { Starport.Loan loan; } diff --git a/src/interfaces/TokenReceiverInterface.sol b/src/interfaces/TokenReceiverInterface.sol index 1b7cc9fd..05b3459e 100644 --- a/src/interfaces/TokenReceiverInterface.sol +++ b/src/interfaces/TokenReceiverInterface.sol @@ -1,3 +1,30 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; interface TokenReceiverInterface { diff --git a/src/lib/PausableNonReentrant.sol b/src/lib/PausableNonReentrant.sol index 32eeb72f..81f9d133 100644 --- a/src/lib/PausableNonReentrant.sol +++ b/src/lib/PausableNonReentrant.sol @@ -1,3 +1,30 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + import {Ownable} from "solady/src/auth/Ownable.sol"; abstract contract PausableNonReentrant is Ownable { diff --git a/src/lib/RefStarportLib.sol b/src/lib/RefStarportLib.sol index 4e04744a..91e06e4e 100644 --- a/src/lib/RefStarportLib.sol +++ b/src/lib/RefStarportLib.sol @@ -1,8 +1,39 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; +import {Starport} from "starport-core/Starport.sol"; + import {ItemType, ReceivedItem, SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; -import {Starport} from "starport-core/Starport.sol"; +/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ +/* LIB ENUMS */ +/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ enum Actions { Nothing, @@ -13,8 +44,16 @@ enum Actions { } library RefStarportLib { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CUSTOM ERRORS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + error InvalidSalt(); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* INTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + function validateSalt( mapping(address => mapping(bytes32 => bool)) storage usedSalts, address borrower, diff --git a/src/lib/StarportLib.sol b/src/lib/StarportLib.sol index ee52c4d8..9bb9d2e4 100644 --- a/src/lib/StarportLib.sol +++ b/src/lib/StarportLib.sol @@ -1,20 +1,56 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; -import {ItemType, ReceivedItem, SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; import {Starport} from "starport-core/Starport.sol"; +import {ItemType, ReceivedItem, SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; + import {ERC721} from "solady/src/tokens/ERC721.sol"; import {ERC20} from "solady/src/tokens/ERC20.sol"; import {ERC1155} from "solady/src/tokens/ERC1155.sol"; import {SafeTransferLib} from "solady/src/utils/SafeTransferLib.sol"; import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; +/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ +/* LIB ENUMS */ +/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + enum Actions { Nothing, Repayment, Settlement } +/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ +/* LIB STRUCTS */ +/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + struct AdditionalTransfer { ItemType itemType; address token; @@ -28,16 +64,41 @@ library StarportLib { using FixedPointMathLib for uint256; using FixedPointMathLib for int256; + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CUSTOM ERRORS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + error InvalidSalt(); error InvalidItemAmount(); error NativeAssetsNotSupported(); error InvalidItemTokenNoCode(); - error InvalidItemIdentifier(); //must be zero for ERC20's + error InvalidItemIdentifier(); // Must be zero for ERC20's error InvalidItemType(); error InvalidTransferLength(); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTANTS AND IMMUTABLES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + uint256 internal constant _INVALID_SALT = 0x81e69d9b00000000000000000000000000000000000000000000000000000000; + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* PUBLIC FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + function calculateSimpleInterest(uint256 delta_t, uint256 amount, uint256 rate, uint256 decimals) + public + pure + returns (uint256) + { + rate /= 365 days; + return ((delta_t * rate) * amount) / 10 ** decimals; + } + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* INTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + function getId(Starport.Loan memory loan) internal pure returns (uint256 loanId) { loanId = uint256(keccak256(abi.encode(loan))); } @@ -51,17 +112,16 @@ library StarportLib { mstore(0x0, borrower) mstore(0x20, usedSalts.slot) - //usedSalts[borrower] - + // usedSalts[borrower] mstore(0x20, keccak256(0x0, 0x40)) mstore(0x0, salt) - //usedSalts[borrower][salt] + // usedSalts[borrower][salt] let loc := keccak256(0x0, 0x40) - //if (usedSalts[borrower][salt] == true) + // if (usedSalts[borrower][salt] == true) if iszero(iszero(sload(loc))) { - //revert InvalidSalt() + // revert InvalidSalt() mstore(0x0, _INVALID_SALT) revert(0x0, 0x04) } @@ -70,6 +130,14 @@ library StarportLib { } } + /** + * @dev Merges an array of SpentItems into ReceivedItems + * @param payment The SpentItem[] for payment + * @param paymentRecipient The recipient address of the payment + * @param carry The SpentItem[] for carry + * @param carryRecipient The recipient address of the carry + * @return consideration An array of ReceivedItems + */ function mergeSpentItemsToReceivedItems( SpentItem[] memory payment, address paymentRecipient, @@ -128,6 +196,11 @@ library StarportLib { } } + /** + * @dev Removes ReceivedItems with zero amounts + * @param consideration The ReceivedItem[] for payment + * @return newConsideration An array of ReceivedItems with zero amounts removed + */ function removeZeroAmountItems(ReceivedItem[] memory consideration) internal pure @@ -221,15 +294,25 @@ library StarportLib { } } - function calculateSimpleInterest(uint256 delta_t, uint256 amount, uint256 rate, uint256 decimals) - public - pure - returns (uint256) - { - rate /= 365 days; - return ((delta_t * rate) * amount) / 10 ** decimals; + function transferSpentItems(SpentItem[] memory transfers, address from, address to, bool safe) internal { + if (transfers.length > 0) { + uint256 i = 0; + for (; i < transfers.length;) { + SpentItem memory transfer = transfers[i]; + _transferItem(transfer.itemType, transfer.token, transfer.identifier, transfer.amount, from, to, safe); + unchecked { + ++i; + } + } + } else { + revert InvalidTransferLength(); + } } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* PRIVATE INTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + function _transferItem( ItemType itemType, address token, @@ -266,19 +349,4 @@ library StarportLib { revert InvalidItemType(); } } - - function transferSpentItems(SpentItem[] memory transfers, address from, address to, bool safe) internal { - if (transfers.length > 0) { - uint256 i = 0; - for (; i < transfers.length;) { - SpentItem memory transfer = transfers[i]; - _transferItem(transfer.itemType, transfer.token, transfer.identifier, transfer.amount, from, to, safe); - unchecked { - ++i; - } - } - } else { - revert InvalidTransferLength(); - } - } } diff --git a/src/lib/Validation.sol b/src/lib/Validation.sol index ce95eb5d..df9c3129 100644 --- a/src/lib/Validation.sol +++ b/src/lib/Validation.sol @@ -1,13 +1,43 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; import {Starport} from "starport-core/Starport.sol"; abstract contract Validation { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EXTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /* * @dev Validates the loan against the module * @param loan The loan to validate * @return bytes4 The validation result */ - function validate(Starport.Loan calldata) external view virtual returns (bytes4); } diff --git a/src/originators/Originator.sol b/src/originators/Originator.sol index 6e3ec04e..00dbfda9 100644 --- a/src/originators/Originator.sol +++ b/src/originators/Originator.sol @@ -1,30 +1,41 @@ // SPDX-License-Identifier: BUSL-1.1 -/** - * ,--, - * ,---.'| - * ,----.. ,---, ,-. | | : - * / / \ ,--.' | ,--, ,--/ /| : : | ,---, - * | : :| | : ,--.'| ,---, .---. ,---. __ ,-.,--. :/ | | ' : ,---.'| - * . | ;. /: : : | |, ,-+-. / | /. ./| ' ,'\ ,' ,'/ /|: : ' / .--.--. ; ; ' | | : .--.--. - * . ; /--` : | |,--. ,--.--. `--'_ ,--.'|' | .-'-. ' | / / |' | |' || ' / / / ' ' | |__ ,--.--. : : : / / ' - * ; | ; | : ' | / \ ,' ,'| | | ,"' | /___/ \: |. ; ,. :| | ,'' | : | : /`./ | | :.'| / \ : |,-.| : /`./ - * | : | | | /' :.--. .-. | ' | | | | / | | .-'.. ' ' .' | |: :' : / | | \| : ;_ ' : ;.--. .-. | | : ' || : ;_ - * . | '___ ' : | | | \__\/: . . | | : | | | | |/___/ \: '' | .; :| | ' ' : |. \\ \ `. | | ./ \__\/: . . | | / : \ \ `. - * ' ; : .'|| | ' | : ," .--.; | ' : |__ | | | |/ . \ ' .\ | : |; : | | | ' \ \`----. \ ; : ; ," .--.; | ' : |: | `----. \ - * ' | '/ :| : :_:,'/ / ,. | | | '.'|| | |--' \ \ ' \ | \ \ / | , ; ' : |--'/ /`--' / | ,/ / / ,. | | | '/ : / /`--' / - * | : / | | ,' ; : .' \; : ;| |/ \ \ |--" `----' ---' ; |,' '--'. / '---' ; : .' \| : |'--'. / - * \ \ .' `--'' | , .-./| , / '---' \ \ | '--' `--'---' | , .-.// \ / `--'---' - * `---` `--`---' ---`-' '---" `--`---' `-'----' - * - * Chainworks Labs - */ +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; import {Starport} from "starport-core/Starport.sol"; -import {SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; import {CaveatEnforcer} from "starport-core/enforcers/CaveatEnforcer.sol"; +import {SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; + abstract contract Originator { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STRUCTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ struct Request { address borrower; CaveatEnforcer.SignedCaveats borrowerCaveat; @@ -34,6 +45,10 @@ abstract contract Originator { bytes approval; } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EXTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /** * @dev Accepts a request with signed data that is decoded by the originator * communicates with Starport to originate a loan diff --git a/src/originators/StrategistOriginator.sol b/src/originators/StrategistOriginator.sol index 682a0772..fa27a090 100644 --- a/src/originators/StrategistOriginator.sol +++ b/src/originators/StrategistOriginator.sol @@ -1,73 +1,73 @@ // SPDX-License-Identifier: BUSL-1.1 -/** - * ,--, - * ,---.'| - * ,----.. ,---, ,-. | | : - * / / \ ,--.' | ,--, ,--/ /| : : | ,---, - * | : :| | : ,--.'| ,---, .---. ,---. __ ,-.,--. :/ | | ' : ,---.'| - * . | ;. /: : : | |, ,-+-. / | /. ./| ' ,'\ ,' ,'/ /|: : ' / .--.--. ; ; ' | | : .--.--. - * . ; /--` : | |,--. ,--.--. `--'_ ,--.'|' | .-'-. ' | / / |' | |' || ' / / / ' ' | |__ ,--.--. : : : / / ' - * ; | ; | : ' | / \ ,' ,'| | | ,"' | /___/ \: |. ; ,. :| | ,'' | : | : /`./ | | :.'| / \ : |,-.| : /`./ - * | : | | | /' :.--. .-. | ' | | | | / | | .-'.. ' ' .' | |: :' : / | | \| : ;_ ' : ;.--. .-. | | : ' || : ;_ - * . | '___ ' : | | | \__\/: . . | | : | | | | |/___/ \: '' | .; :| | ' ' : |. \\ \ `. | | ./ \__\/: . . | | / : \ \ `. - * ' ; : .'|| | ' | : ," .--.; | ' : |__ | | | |/ . \ ' .\ | : |; : | | | ' \ \`----. \ ; : ; ," .--.; | ' : |: | `----. \ - * ' | '/ :| : :_:,'/ / ,. | | | '.'|| | |--' \ \ ' \ | \ \ / | , ; ' : |--'/ /`--' / | ,/ / / ,. | | | '/ : / /`--' / - * | : / | | ,' ; : .' \; : ;| |/ \ \ |--" `----' ---' ; |,' '--'. / '---' ; : .' \| : |'--'. / - * \ \ .' `--'' | , .-./| , / '---' \ \ | '--' `--'---' | , .-.// \ / `--'---' - * `---` `--`---' ---`-' '---" `--`---' `-'----' - * - * Chainworks Labs - */ +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; import {Starport} from "starport-core/Starport.sol"; - -import {ItemType, ReceivedItem, SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; +import {CaveatEnforcer} from "starport-core/enforcers/CaveatEnforcer.sol"; +import {Originator} from "starport-core/originators/Originator.sol"; import {AdditionalTransfer} from "starport-core/lib/StarportLib.sol"; + import {ConduitControllerInterface} from "seaport-types/src/interfaces/ConduitControllerInterface.sol"; import {ConduitInterface} from "seaport-types/src/interfaces/ConduitInterface.sol"; - +import {ItemType, ReceivedItem, SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; import {ECDSA} from "solady/src/utils/ECDSA.sol"; -import {SignatureCheckerLib} from "solady/src/utils/SignatureCheckerLib.sol"; import {Ownable} from "solady/src/auth/Ownable.sol"; -import {Originator} from "starport-core/originators/Originator.sol"; -import {CaveatEnforcer} from "starport-core/enforcers/CaveatEnforcer.sol"; +import {SignatureCheckerLib} from "solady/src/utils/SignatureCheckerLib.sol"; // Validator abstract contract that lays out the necessary structure and functions for the validator contract StrategistOriginator is Ownable, Originator { - event StrategistTransferred(address newStrategist); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CUSTOM ERRORS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ - mapping(bytes32 => bool) public usedHashes; - - struct Details { - address custodian; - address issuer; - uint256 deadline; - Offer offer; - } + error AdditionalTransferError(); + error InvalidCollateral(); + error InvalidCustodian(); + error InvalidDeadline(); + error InvalidDebt(); + error InvalidDebtAmount(); + error InvalidDebtLength(); + error InvalidOffer(); + error InvalidSigner(); + error NotAuthorized(); + error NotStarport(); - struct Offer { - bytes32 salt; //can be bytes32(0) if so do not invalidate the hash - Starport.Terms terms; - SpentItem[] collateral; - SpentItem[] debt; - } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EVENTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ event CounterUpdated(uint256); - event HashInvalidated(bytes32 hash); + event StrategistTransferred(address newStrategist); - error NotStarport(); - error NotAuthorized(); - error InvalidDebt(); - error InvalidDebtLength(); - error InvalidDebtAmount(); - error InvalidCustodian(); - error InvalidCollateral(); - error InvalidDeadline(); - error InvalidOffer(); - error InvalidSigner(); - error AdditionalTransferError(); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTANTS AND IMMUTABLES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ Starport public immutable SP; @@ -75,14 +75,41 @@ contract StrategistOriginator is Ownable, Originator { bytes32 constant EIP_DOMAIN = keccak256("EIP712Domain(string version,uint256 chainId,address verifyingContract)"); bytes32 public constant ORIGINATOR_DETAILS_TYPEHASH = keccak256("Origination(uint256 nonce,bytes32 hash)"); bytes32 constant VERSION = keccak256("0"); - bytes32 internal immutable _DOMAIN_SEPARATOR; + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STORAGE */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + mapping(bytes32 => bool) public usedHashes; + // Strategist address and fee address public strategist; uint256 public strategistFee; uint256 private _counter; + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STRUCTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + struct Details { + address custodian; + address issuer; + uint256 deadline; + Offer offer; + } + + struct Offer { + bytes32 salt; // If bytes32(0) do not invalidate the hash + Starport.Terms terms; + SpentItem[] collateral; + SpentItem[] debt; + } + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTRUCTOR */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + constructor(Starport SP_, address strategist_, uint256 fee_, address owner) { _initializeOwner(owner); strategist = strategist_; @@ -99,41 +126,19 @@ contract StrategistOriginator is Ownable, Originator { ); } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EXTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /** - * @dev sets the strategist address - * @param newStrategist The new strategist address + * @dev Sets the strategist address + * @param newStrategist The new strategist address */ function setStrategist(address newStrategist) external onlyOwner { strategist = newStrategist; emit StrategistTransferred(newStrategist); } - /** - * @dev returns data that is encodePacked for signing - * @param contextHash The hash of the data being signed - */ - function encodeWithAccountCounter(bytes32 contextHash) public view virtual returns (bytes memory) { - bytes32 hash = keccak256(abi.encode(ORIGINATOR_DETAILS_TYPEHASH, _counter, contextHash)); - - return abi.encodePacked(bytes1(0x19), bytes1(0x01), _DOMAIN_SEPARATOR, hash); - } - /** - * @dev returns the strategist and fee - * @return strategist address and fee - */ - - function getStrategistData() public view virtual returns (address, uint256) { - return (strategist, strategistFee); - } - - /** - * @dev returns the nonce of the contract - * @return _counter - */ - function getCounter() public view virtual returns (uint256) { - return _counter; - } - /** * @dev increments the Counter to invalidate any open offers */ @@ -145,26 +150,18 @@ contract StrategistOriginator is Ownable, Originator { emit CounterUpdated(_counter); } - /** - * @dev returns the domain separator - * @return _DOMAIN_SEPARATOR - */ - function domainSeparator() public view virtual returns (bytes32) { - return _DOMAIN_SEPARATOR; - } - /** * @dev Accepts a request with signed data that is decoded by the originator * communicates with Starport to originate a loan - * @param params The request for the origination + * @param params The request for the origination */ function originate(Request calldata params) external virtual override { Details memory details = abi.decode(params.details, (Details)); _validateOffer(params, details); Starport.Loan memory loan = Starport.Loan({ - start: uint256(0), // are set in the loan manager - originator: address(0), // are set in the loan manager + start: uint256(0), // Set in the loan manager + originator: address(0), // Set in the loan manager custodian: details.custodian, issuer: details.issuer, borrower: params.borrower, @@ -177,13 +174,54 @@ contract StrategistOriginator is Ownable, Originator { SP.originate(new AdditionalTransfer[](0), params.borrowerCaveat, le, loan); } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* PUBLIC FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /** + * @dev Returns data that is encodePacked for signing + * @param contextHash The hash of the data being signed + */ + function encodeWithAccountCounter(bytes32 contextHash) public view virtual returns (bytes memory) { + bytes32 hash = keccak256(abi.encode(ORIGINATOR_DETAILS_TYPEHASH, _counter, contextHash)); + + return abi.encodePacked(bytes1(0x19), bytes1(0x01), _DOMAIN_SEPARATOR, hash); + } + /** + * @dev Returns the strategist and fee + * @return strategist address and fee + */ + + function getStrategistData() public view virtual returns (address, uint256) { + return (strategist, strategistFee); + } + + /** + * @dev Returns the nonce of the contract + * @return _counter + */ + function getCounter() public view virtual returns (uint256) { + return _counter; + } + + /** + * @dev Returns the domain separator + * @return _DOMAIN_SEPARATOR + */ + function domainSeparator() public view virtual returns (bytes32) { + return _DOMAIN_SEPARATOR; + } + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* INTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + function _validateAsk(Request calldata request, Details memory details) internal virtual { if (keccak256(abi.encode(request.collateral)) != keccak256(abi.encode(details.offer.collateral))) { revert InvalidCollateral(); } - //loop through collateral and check if the collateral is the same - + // Loop through collateral and check if the collateral is the same for (uint256 i = 0; i < request.debt.length;) { if ( request.debt[i].itemType != details.offer.debt[i].itemType @@ -212,7 +250,6 @@ contract StrategistOriginator is Ownable, Originator { revert InvalidDebtLength(); } _validateAsk(request, details); - if (details.offer.salt != bytes32(0)) { if (!usedHashes[contextHash]) { usedHashes[contextHash] = true; diff --git a/src/pricing/BasePricing.sol b/src/pricing/BasePricing.sol index 75ac5a8b..b8f1cefe 100644 --- a/src/pricing/BasePricing.sol +++ b/src/pricing/BasePricing.sol @@ -1,45 +1,70 @@ // SPDX-License-Identifier: BUSL-1.1 -/** - * ,--, - * ,---.'| - * ,----.. ,---, ,-. | | : - * / / \ ,--.' | ,--, ,--/ /| : : | ,---, - * | : :| | : ,--.'| ,---, .---. ,---. __ ,-.,--. :/ | | ' : ,---.'| - * . | ;. /: : : | |, ,-+-. / | /. ./| ' ,'\ ,' ,'/ /|: : ' / .--.--. ; ; ' | | : .--.--. - * . ; /--` : | |,--. ,--.--. `--'_ ,--.'|' | .-'-. ' | / / |' | |' || ' / / / ' ' | |__ ,--.--. : : : / / ' - * ; | ; | : ' | / \ ,' ,'| | | ,"' | /___/ \: |. ; ,. :| | ,'' | : | : /`./ | | :.'| / \ : |,-.| : /`./ - * | : | | | /' :.--. .-. | ' | | | | / | | .-'.. ' ' .' | |: :' : / | | \| : ;_ ' : ;.--. .-. | | : ' || : ;_ - * . | '___ ' : | | | \__\/: . . | | : | | | | |/___/ \: '' | .; :| | ' ' : |. \\ \ `. | | ./ \__\/: . . | | / : \ \ `. - * ' ; : .'|| | ' | : ," .--.; | ' : |__ | | | |/ . \ ' .\ | : |; : | | | ' \ \`----. \ ; : ; ," .--.; | ' : |: | `----. \ - * ' | '/ :| : :_:,'/ / ,. | | | '.'|| | |--' \ \ ' \ | \ \ / | , ; ' : |--'/ /`--' / | ,/ / / ,. | | | '/ : / /`--' / - * | : / | | ,' ; : .' \; : ;| |/ \ \ |--" `----' ---' ; |,' '--'. / '---' ; : .' \| : |'--'. / - * \ \ .' `--'' | , .-./| , / '---' \ \ | '--' `--'---' | , .-.// \ / `--'---' - * `---` `--`---' ---`-' '---" `--`---' `-'----' - * - * Chainworks Labs - */ +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; import {Starport} from "starport-core/Starport.sol"; import {Pricing} from "starport-core/pricing/Pricing.sol"; -import {ReceivedItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; import {Status} from "starport-core/status/Status.sol"; -import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; - +import {Validation} from "starport-core/lib/Validation.sol"; import {StarportLib} from "starport-core/lib/StarportLib.sol"; + +import {ReceivedItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; import {SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; -import {Validation} from "starport-core/lib/Validation.sol"; +import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; abstract contract BasePricing is Pricing { using FixedPointMathLib for uint256; using {StarportLib.getId} for Starport.Loan; + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STRUCTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + struct Details { uint256 rate; uint256 carryRate; uint256 decimals; } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EXTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + // @inheritdoc Validation + function validate(Starport.Loan calldata loan) external view virtual override returns (bytes4) { + Details memory details = abi.decode(loan.terms.pricingData, (Details)); + return (details.decimals > 0) ? Validation.validate.selector : bytes4(0xFFFFFFFF); + } + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* PUBLIC FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + // @inheritdoc Pricing function getPaymentConsideration(Starport.Loan calldata loan) public @@ -87,12 +112,6 @@ abstract contract BasePricing is Pricing { } } - // @inheritdoc Validation - function validate(Starport.Loan calldata loan) external view virtual override returns (bytes4) { - Details memory details = abi.decode(loan.terms.pricingData, (Details)); - return (details.decimals > 0) ? Validation.validate.selector : bytes4(0xFFFFFFFF); - } - /** * @dev Computes the interest for a given loan * @param loan The loan to compute the interest for diff --git a/src/pricing/Pricing.sol b/src/pricing/Pricing.sol index 5188ab11..ef6c2274 100644 --- a/src/pricing/Pricing.sol +++ b/src/pricing/Pricing.sol @@ -1,42 +1,62 @@ // SPDX-License-Identifier: BUSL-1.1 -/** - * ,--, - * ,---.'| - * ,----.. ,---, ,-. | | : - * / / \ ,--.' | ,--, ,--/ /| : : | ,---, - * | : :| | : ,--.'| ,---, .---. ,---. __ ,-.,--. :/ | | ' : ,---.'| - * . | ;. /: : : | |, ,-+-. / | /. ./| ' ,'\ ,' ,'/ /|: : ' / .--.--. ; ; ' | | : .--.--. - * . ; /--` : | |,--. ,--.--. `--'_ ,--.'|' | .-'-. ' | / / |' | |' || ' / / / ' ' | |__ ,--.--. : : : / / ' - * ; | ; | : ' | / \ ,' ,'| | | ,"' | /___/ \: |. ; ,. :| | ,'' | : | : /`./ | | :.'| / \ : |,-.| : /`./ - * | : | | | /' :.--. .-. | ' | | | | / | | .-'.. ' ' .' | |: :' : / | | \| : ;_ ' : ;.--. .-. | | : ' || : ;_ - * . | '___ ' : | | | \__\/: . . | | : | | | | |/___/ \: '' | .; :| | ' ' : |. \\ \ `. | | ./ \__\/: . . | | / : \ \ `. - * ' ; : .'|| | ' | : ," .--.; | ' : |__ | | | |/ . \ ' .\ | : |; : | | | ' \ \`----. \ ; : ; ," .--.; | ' : |: | `----. \ - * ' | '/ :| : :_:,'/ / ,. | | | '.'|| | |--' \ \ ' \ | \ \ / | , ; ' : |--'/ /`--' / | ,/ / / ,. | | | '/ : / /`--' / - * | : / | | ,' ; : .' \; : ;| |/ \ \ |--" `----' ---' ; |,' '--'. / '---' ; : .' \| : |'--'. / - * \ \ .' `--'' | , .-./| , / '---' \ \ | '--' `--'---' | , .-.// \ / `--'---' - * `---` `--`---' ---`-' '---" `--`---' `-'----' - * - * Chainworks Labs - */ +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; import {Starport} from "starport-core/Starport.sol"; -import {SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; import {AdditionalTransfer} from "starport-core/lib/StarportLib.sol"; import {Validation} from "starport-core/lib/Validation.sol"; +import {SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; + abstract contract Pricing is Validation { Starport public immutable SP; + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CUSTOM ERRORS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + error InvalidRefinance(); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTRUCTOR */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + constructor(Starport SP_) { SP = SP_; } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* PUBLIC FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /** * @dev computes the payment details for a loan - * @param loan The loan to compute the payment details for + * @param loan The loan to compute the payment details for */ function getPaymentConsideration(Starport.Loan calldata loan) public @@ -44,11 +64,15 @@ abstract contract Pricing is Validation { virtual returns (SpentItem[] memory, SpentItem[] memory); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EXTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /** * @dev computes the refinance details for a loan - * @param loan The loan to compute the payment details for - * @param newPricingData The new pricing data being offered - * @param fulfiller The address of the fulfiller + * @param loan The loan to compute the payment details for + * @param newPricingData The new pricing data being offered + * @param fulfiller The address of the fulfiller */ function getRefinanceConsideration(Starport.Loan calldata loan, bytes calldata newPricingData, address fulfiller) external diff --git a/src/pricing/SimpleInterestPricing.sol b/src/pricing/SimpleInterestPricing.sol index 97906cde..55ef4e75 100644 --- a/src/pricing/SimpleInterestPricing.sol +++ b/src/pricing/SimpleInterestPricing.sol @@ -1,39 +1,54 @@ // SPDX-License-Identifier: BUSL-1.1 -/** - * ,--, - * ,---.'| - * ,----.. ,---, ,-. | | : - * / / \ ,--.' | ,--, ,--/ /| : : | ,---, - * | : :| | : ,--.'| ,---, .---. ,---. __ ,-.,--. :/ | | ' : ,---.'| - * . | ;. /: : : | |, ,-+-. / | /. ./| ' ,'\ ,' ,'/ /|: : ' / .--.--. ; ; ' | | : .--.--. - * . ; /--` : | |,--. ,--.--. `--'_ ,--.'|' | .-'-. ' | / / |' | |' || ' / / / ' ' | |__ ,--.--. : : : / / ' - * ; | ; | : ' | / \ ,' ,'| | | ,"' | /___/ \: |. ; ,. :| | ,'' | : | : /`./ | | :.'| / \ : |,-.| : /`./ - * | : | | | /' :.--. .-. | ' | | | | / | | .-'.. ' ' .' | |: :' : / | | \| : ;_ ' : ;.--. .-. | | : ' || : ;_ - * . | '___ ' : | | | \__\/: . . | | : | | | | |/___/ \: '' | .; :| | ' ' : |. \\ \ `. | | ./ \__\/: . . | | / : \ \ `. - * ' ; : .'|| | ' | : ," .--.; | ' : |__ | | | |/ . \ ' .\ | : |; : | | | ' \ \`----. \ ; : ; ," .--.; | ' : |: | `----. \ - * ' | '/ :| : :_:,'/ / ,. | | | '.'|| | |--' \ \ ' \ | \ \ / | , ; ' : |--'/ /`--' / | ,/ / / ,. | | | '/ : / /`--' / - * | : / | | ,' ; : .' \; : ;| |/ \ \ |--" `----' ---' ; |,' '--'. / '---' ; : .' \| : |'--'. / - * \ \ .' `--'' | , .-./| , / '---' \ \ | '--' `--'---' | , .-.// \ / `--'---' - * `---` `--`---' ---`-' '---" `--`---' `-'----' - * - * Chainworks Labs - */ +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; -import {ReceivedItem, BasePricing} from "starport-core/pricing/BasePricing.sol"; -import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; import {Starport} from "starport-core/Starport.sol"; +import {ReceivedItem, BasePricing} from "starport-core/pricing/BasePricing.sol"; import {Pricing} from "starport-core/pricing/Pricing.sol"; -import {AdditionalTransfer} from "starport-core/lib/StarportLib.sol"; -import {SpentItem, ReceivedItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; -import {StarportLib} from "starport-core/lib/StarportLib.sol"; import {Validation} from "starport-core/lib/Validation.sol"; +import {StarportLib, AdditionalTransfer} from "starport-core/lib/StarportLib.sol"; + +import {SpentItem, ReceivedItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; +import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; contract SimpleInterestPricing is BasePricing { using FixedPointMathLib for uint256; + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTRUCTOR */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + constructor(Starport SP_) Pricing(SP_) {} + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* PUBLIC FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + // @inheritdoc BasePricing function calculateInterest(uint256 delta_t, uint256 amount, uint256 rate, uint256 decimals) public @@ -44,6 +59,10 @@ contract SimpleInterestPricing is BasePricing { return StarportLib.calculateSimpleInterest(delta_t, amount, rate, decimals); } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EXTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + // @inheritdoc Validation function validate(Starport.Loan calldata loan) external view override returns (bytes4) { Details memory details = abi.decode(loan.terms.pricingData, (Details)); diff --git a/src/settlement/DutchAuctionSettlement.sol b/src/settlement/DutchAuctionSettlement.sol index 0610be06..cb5a2721 100644 --- a/src/settlement/DutchAuctionSettlement.sol +++ b/src/settlement/DutchAuctionSettlement.sol @@ -1,3 +1,30 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; import { @@ -17,18 +44,34 @@ import {BasePricing} from "starport-core/pricing/BasePricing.sol"; import {Validation} from "starport-core/lib/Validation.sol"; abstract contract DutchAuctionSettlement is Settlement, AmountDeriver { - constructor(Starport SP_) Settlement(SP_) {} - using FixedPointMathLib for uint256; + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CUSTOM ERRORS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + error InvalidAmount(); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTRUCTOR */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + constructor(Starport SP_) Settlement(SP_) {} + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STRUCTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + struct Details { uint256 startingPrice; uint256 endingPrice; uint256 window; } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EXTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + // @inheritdoc Settlement function postSettlement(Starport.Loan calldata loan, address fulfiller) external @@ -44,11 +87,21 @@ abstract contract DutchAuctionSettlement is Settlement, AmountDeriver { return Settlement.postRepayment.selector; } - /* - * @dev get the start of the auction - * @param loan The loan in question - * @return uint256 The start of the auction - */ + // @inheritdoc Validation + function validate(Starport.Loan calldata loan) external view virtual override returns (bytes4) { + Details memory details = abi.decode(loan.terms.settlementData, (Details)); + return (details.startingPrice > details.endingPrice) ? Validation.validate.selector : bytes4(0xFFFFFFFF); + } + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* PUBLIC FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /** + * @dev Get the start of the auction + * @param loan The loan in question + * @return uint256 The start of the auction + */ function getAuctionStart(Starport.Loan calldata loan) public view virtual returns (uint256); // @inheritdoc Settlement @@ -106,10 +159,4 @@ abstract contract DutchAuctionSettlement is Settlement, AmountDeriver { recipient: payable(loan.issuer) }); } - - // @inheritdoc Validation - function validate(Starport.Loan calldata loan) external view virtual override returns (bytes4) { - Details memory details = abi.decode(loan.terms.settlementData, (Details)); - return (details.startingPrice > details.endingPrice) ? Validation.validate.selector : bytes4(0xFFFFFFFF); - } } diff --git a/src/settlement/FixedTermDutchAuctionSettlement.sol b/src/settlement/FixedTermDutchAuctionSettlement.sol index 208e4bbd..8352b1a9 100644 --- a/src/settlement/FixedTermDutchAuctionSettlement.sol +++ b/src/settlement/FixedTermDutchAuctionSettlement.sol @@ -1,19 +1,55 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; -import {Settlement} from "starport-core/settlement/Settlement.sol"; import {Starport} from "starport-core/Starport.sol"; -import {SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; -import {FixedTermStatus} from "starport-core/status/FixedTermStatus.sol"; import {DutchAuctionSettlement} from "starport-core/settlement/DutchAuctionSettlement.sol"; +import {FixedTermStatus} from "starport-core/status/FixedTermStatus.sol"; +import {Settlement} from "starport-core/settlement/Settlement.sol"; import {StarportLib} from "starport-core/lib/StarportLib.sol"; + import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; +import {SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; contract FixedTermDutchAuctionSettlement is DutchAuctionSettlement { using {StarportLib.getId} for Starport.Loan; using FixedPointMathLib for uint256; + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTRUCTOR */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + constructor(Starport SP_) DutchAuctionSettlement(SP_) {} + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EXTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + // @inheritdoc DutchAuctionSettlement function getAuctionStart(Starport.Loan calldata loan) public view virtual override returns (uint256) { FixedTermStatus.Details memory details = abi.decode(loan.terms.statusData, (FixedTermStatus.Details)); diff --git a/src/settlement/Settlement.sol b/src/settlement/Settlement.sol index 57eed356..3c3213a4 100644 --- a/src/settlement/Settlement.sol +++ b/src/settlement/Settlement.sol @@ -1,56 +1,79 @@ // SPDX-License-Identifier: BUSL-1.1 -/** - * ,--, - * ,---.'| - * ,----.. ,---, ,-. | | : - * / / \ ,--.' | ,--, ,--/ /| : : | ,---, - * | : :| | : ,--.'| ,---, .---. ,---. __ ,-.,--. :/ | | ' : ,---.'| - * . | ;. /: : : | |, ,-+-. / | /. ./| ' ,'\ ,' ,'/ /|: : ' / .--.--. ; ; ' | | : .--.--. - * . ; /--` : | |,--. ,--.--. `--'_ ,--.'|' | .-'-. ' | / / |' | |' || ' / / / ' ' | |__ ,--.--. : : : / / ' - * ; | ; | : ' | / \ ,' ,'| | | ,"' | /___/ \: |. ; ,. :| | ,'' | : | : /`./ | | :.'| / \ : |,-.| : /`./ - * | : | | | /' :.--. .-. | ' | | | | / | | .-'.. ' ' .' | |: :' : / | | \| : ;_ ' : ;.--. .-. | | : ' || : ;_ - * . | '___ ' : | | | \__\/: . . | | : | | | | |/___/ \: '' | .; :| | ' ' : |. \\ \ `. | | ./ \__\/: . . | | / : \ \ `. - * ' ; : .'|| | ' | : ," .--.; | ' : |__ | | | |/ . \ ' .\ | : |; : | | | ' \ \`----. \ ; : ; ," .--.; | ' : |: | `----. \ - * ' | '/ :| : :_:,'/ / ,. | | | '.'|| | |--' \ \ ' \ | \ \ / | , ; ' : |--'/ /`--' / | ,/ / / ,. | | | '/ : / /`--' / - * | : / | | ,' ; : .' \; : ;| |/ \ \ |--" `----' ---' ; |,' '--'. / '---' ; : .' \| : |'--'. / - * \ \ .' `--'' | , .-./| , / '---' \ \ | '--' `--'---' | , .-.// \ / `--'---' - * `---` `--`---' ---`-' '---" `--`---' `-'----' - * - * Chainworks Labs - */ +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; import {Starport} from "starport-core/Starport.sol"; +import {Validation} from "starport-core/lib/Validation.sol"; import {ReceivedItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; -import {Validation} from "starport-core/lib/Validation.sol"; abstract contract Settlement is Validation { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTANTS AND IMMUTABLES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + Starport public immutable SP; + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CONSTRUCTOR */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + constructor(Starport SP_) { SP = SP_; } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EXTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /* * @dev Called by the Custodian after a loan has been settled - * @param loan The loan that has been settled + * @param loan The loan that has been settled * @param fulfiller The address of the fulfiller */ function postSettlement(Starport.Loan calldata loan, address fulfiller) external virtual returns (bytes4); /* * @dev Called by the Starport/Custodian after a loan has been repaid - * @param loan The loan that has been settled + * @param loan The loan that has been settled * @param fulfiller The address of the fulfiller */ function postRepayment(Starport.Loan calldata loan, address fulfiller) external virtual returns (bytes4); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* PUBLIC FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /* * @dev helper to get the consideration for a loan - * @param loan The loan in question + * @param loan The loan in question * @return consideration The settlement consideration for the loan - * @return authorized The address of the authorized party (if any) + * @return address The address of the authorized party (if any) */ function getSettlementConsideration(Starport.Loan calldata loan) public @@ -58,6 +81,10 @@ abstract contract Settlement is Validation { virtual returns (ReceivedItem[] memory consideration, address authorized); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* FUNCTION OVERRIDES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /* * @dev standard erc1155 received hook */ diff --git a/src/status/FixedTermStatus.sol b/src/status/FixedTermStatus.sol index ddb1bef7..b3050b6a 100644 --- a/src/status/FixedTermStatus.sol +++ b/src/status/FixedTermStatus.sol @@ -1,3 +1,30 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; import {Starport} from "starport-core/Starport.sol"; @@ -5,10 +32,18 @@ import {Status} from "starport-core/status/Status.sol"; import {Validation} from "starport-core/lib/Validation.sol"; contract FixedTermStatus is Status { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STRUCTS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + struct Details { uint256 loanDuration; } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EXTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + // @inheritdoc Status function isActive(Starport.Loan calldata loan, bytes calldata extraData) external view override returns (bool) { Details memory details = abi.decode(loan.terms.statusData, (Details)); diff --git a/src/status/Status.sol b/src/status/Status.sol index ec1cecae..9492e957 100644 --- a/src/status/Status.sol +++ b/src/status/Status.sol @@ -1,29 +1,40 @@ // SPDX-License-Identifier: BUSL-1.1 -/** - * ,--, - * ,---.'| - * ,----.. ,---, ,-. | | : - * / / \ ,--.' | ,--, ,--/ /| : : | ,---, - * | : :| | : ,--.'| ,---, .---. ,---. __ ,-.,--. :/ | | ' : ,---.'| - * . | ;. /: : : | |, ,-+-. / | /. ./| ' ,'\ ,' ,'/ /|: : ' / .--.--. ; ; ' | | : .--.--. - * . ; /--` : | |,--. ,--.--. `--'_ ,--.'|' | .-'-. ' | / / |' | |' || ' / / / ' ' | |__ ,--.--. : : : / / ' - * ; | ; | : ' | / \ ,' ,'| | | ,"' | /___/ \: |. ; ,. :| | ,'' | : | : /`./ | | :.'| / \ : |,-.| : /`./ - * | : | | | /' :.--. .-. | ' | | | | / | | .-'.. ' ' .' | |: :' : / | | \| : ;_ ' : ;.--. .-. | | : ' || : ;_ - * . | '___ ' : | | | \__\/: . . | | : | | | | |/___/ \: '' | .; :| | ' ' : |. \\ \ `. | | ./ \__\/: . . | | / : \ \ `. - * ' ; : .'|| | ' | : ," .--.; | ' : |__ | | | |/ . \ ' .\ | : |; : | | | ' \ \`----. \ ; : ; ," .--.; | ' : |: | `----. \ - * ' | '/ :| : :_:,'/ / ,. | | | '.'|| | |--' \ \ ' \ | \ \ / | , ; ' : |--'/ /`--' / | ,/ / / ,. | | | '/ : / /`--' / - * | : / | | ,' ; : .' \; : ;| |/ \ \ |--" `----' ---' ; |,' '--'. / '---' ; : .' \| : |'--'. / - * \ \ .' `--'' | , .-./| , / '---' \ \ | '--' `--'---' | , .-.// \ / `--'---' - * `---` `--`---' ---`-' '---" `--`---' `-'----' - * - * Chainworks Labs - */ +// +// ↑↑↑↑ ↑↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑ ↑ +// ↑↑↑↑ ↑↑↑↑↑ +// ↑ ↑↑↑↑ ↑ ↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑↑ ↑↑ ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ ↑↑ ↑↑↑ ↑↑↑↑↑↑ ↑↑↑↑↑↑ ↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑↑ ↑↑↑ +// ↑↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑ Starport: Lending Kernel +// ↑ ↑↑↑↑ ↑↑↑↑↑ +// ↑↑↑↑ ↑↑↑↑↑ Designed with love by Astaria Labs, Inc +// ↑↑↑↑ ↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ +// ↑↑↑↑ + pragma solidity ^0.8.17; import {Starport} from "starport-core/Starport.sol"; import {Validation} from "starport-core/lib/Validation.sol"; abstract contract Status is Validation { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* EXTERNAL FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /* * @dev Returns true if the loan is still active, false otherwise. * @param loan The loan to check.